y_petri 2.0.14 → 2.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/y_petri/manipulator/simulation_related_methods.rb +10 -5
- data/lib/y_petri/net.rb +4 -4
- data/lib/y_petri/place/guard.rb +17 -12
- data/lib/y_petri/simulation/collections.rb +460 -0
- data/lib/y_petri/{timed_simulation.rb → simulation/timed.rb} +55 -68
- data/lib/y_petri/simulation.rb +192 -724
- data/lib/y_petri/transition/construction.rb +1 -1
- data/lib/y_petri/transition.rb +82 -86
- data/lib/y_petri/version.rb +1 -1
- data/lib/y_petri/workspace/parametrized_subclassing.rb +2 -1
- data/lib/y_petri.rb +1 -2
- data/test/acceptance/basic_usage_test.rb +1 -1
- data/test/manipulator_test.rb +1 -1
- data/test/net_test.rb +2 -1
- data/test/place_test.rb +3 -1
- data/test/simulation_test.rb +14 -13
- data/test/timed_simulation_test.rb +30 -26
- data/test/workspace_test.rb +1 -1
- data/test/y_petri_test.rb +2 -4
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c819010da78d8924cb320612edc32744c5d745a
|
4
|
+
data.tar.gz: f3320f25920735b13fa67be3793fa3dd768915fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e65d106f512773919f4fcf810927ac7f61c8c0e50c0faeea4b23c7671b2ae175a770ef8ce4da9d08366eb14b55e021b7949965b9c55de7f86f501d8f25128561
|
7
|
+
data.tar.gz: 834d55aeb5103d792a2ff8370352802278815fea76c6286bb465e59973a9e9166c24bce73309d20da1ca85303581cf0ac5cfc015c763f26a3287024dcbc37cdc
|
@@ -192,14 +192,19 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
192
192
|
end
|
193
193
|
alias set_step_size set_step
|
194
194
|
|
195
|
-
#
|
196
|
-
# settings collection).
|
195
|
+
# Sets the time frame of the current ssc (sim. settings collection).
|
197
196
|
#
|
198
|
-
def set_time
|
199
|
-
ssc.update
|
197
|
+
def set_time time_range
|
198
|
+
ssc.update time: time_range.aT_kind_of( Range )
|
200
199
|
end
|
201
|
-
alias set_target_time set_time
|
202
200
|
|
201
|
+
# Sets the time frame of the current ssc to run from zero to the time supplied
|
202
|
+
# as the argument.
|
203
|
+
#
|
204
|
+
def set_target_time time
|
205
|
+
set_time time * 0 .. time
|
206
|
+
end
|
207
|
+
|
203
208
|
# Changes the sampling period of the current ssc (ssc = simulation
|
204
209
|
# settings collection).
|
205
210
|
#
|
data/lib/y_petri/net.rb
CHANGED
@@ -113,14 +113,14 @@ class YPetri::Net
|
|
113
113
|
|
114
114
|
# Creates a new simulation from the net.
|
115
115
|
#
|
116
|
-
def new_simulation( **
|
117
|
-
YPetri::Simulation.new **
|
116
|
+
def new_simulation( **nn )
|
117
|
+
YPetri::Simulation.new **nn.merge( net: self )
|
118
118
|
end
|
119
119
|
|
120
120
|
# Creates a new timed simulation from the net.
|
121
121
|
#
|
122
|
-
def new_timed_simulation( **
|
123
|
-
|
122
|
+
def new_timed_simulation( **nn )
|
123
|
+
new_simulation( **nn ).aT &:timed?
|
124
124
|
end
|
125
125
|
|
126
126
|
# Networks are equal when their places and transitions are equal.
|
data/lib/y_petri/place/guard.rb
CHANGED
@@ -6,9 +6,13 @@ class YPetri::Place
|
|
6
6
|
# Marking guard.
|
7
7
|
#
|
8
8
|
class Guard
|
9
|
-
ERRMSG = -> m,
|
9
|
+
ERRMSG = -> m, of, assert do
|
10
|
+
"Marking #{m}:#{m.class}" +
|
11
|
+
if of then " of #{of.name || of rescue of}" else '' end +
|
12
|
+
" #{assert}!"
|
13
|
+
end
|
10
14
|
|
11
|
-
attr_reader :assertion, :block
|
15
|
+
attr_reader :place, :assertion, :block
|
12
16
|
|
13
17
|
# Requires a NL guard assertion (used in GuardError messages), and a guard
|
14
18
|
# block expressing the same assertion formally, in code. Attention: *Only
|
@@ -21,8 +25,8 @@ class YPetri::Place
|
|
21
25
|
# automatically raise appropriately worded +GuardError+. See also:
|
22
26
|
# {+YPetri#guard+ method}[rdoc-ref:YPetri::guard].
|
23
27
|
#
|
24
|
-
def initialize assertion_NL_string, &block
|
25
|
-
@assertion, @block = assertion_NL_string, block
|
28
|
+
def initialize( assertion_NL_string, place: nil, &block )
|
29
|
+
@place, @assertion, @block = place, assertion_NL_string, block
|
26
30
|
@Lab = Class.new BasicObject do
|
27
31
|
def initialize λ; @λ = λ end
|
28
32
|
def fail; @λ.call end
|
@@ -32,9 +36,9 @@ class YPetri::Place
|
|
32
36
|
# Validates a supplied marking value against the guard block. Raises
|
33
37
|
# +YPetri::GuardError+ if the guard fails, otherwise returns _true_.
|
34
38
|
#
|
35
|
-
def validate(
|
36
|
-
λ = __fail__(
|
37
|
-
λ.call if @Lab.new( λ ).instance_exec(
|
39
|
+
def validate( marking )
|
40
|
+
λ = __fail__( marking, assertion )
|
41
|
+
λ.call if @Lab.new( λ ).instance_exec( marking, &block ) == false
|
38
42
|
return true
|
39
43
|
end
|
40
44
|
|
@@ -42,8 +46,9 @@ class YPetri::Place
|
|
42
46
|
|
43
47
|
# Constructs the fail closure.
|
44
48
|
#
|
45
|
-
def __fail__
|
46
|
-
|
49
|
+
def __fail__ marking, assertion
|
50
|
+
pl = place
|
51
|
+
-> { fail YPetri::GuardError, ERRMSG.( marking, pl, assertion ) }
|
47
52
|
end
|
48
53
|
end
|
49
54
|
|
@@ -80,7 +85,7 @@ class YPetri::Place
|
|
80
85
|
# were given (behaving as +#federated_guard_closure+ alias in this case).
|
81
86
|
#
|
82
87
|
def guard *args, &block
|
83
|
-
if block then @guards << Guard.new( *args, &block )
|
88
|
+
if block then @guards << Guard.new( *args, place: name || self, &block )
|
84
89
|
elsif args.size == 1 then federated_guard_closure.( args[0] )
|
85
90
|
elsif args.empty? then federated_guard_closure
|
86
91
|
end
|
@@ -91,8 +96,8 @@ class YPetri::Place
|
|
91
96
|
# blocks pass for the given marking value.
|
92
97
|
#
|
93
98
|
def federated_guard_closure
|
94
|
-
lineup = guards.dup
|
95
|
-
-> m { lineup.each { |g| g.validate m }; return m }
|
99
|
+
place_name, lineup = name.to_s, guards.dup
|
100
|
+
-> m { lineup.each { |g| g.validate( m ) }; return m }
|
96
101
|
end
|
97
102
|
|
98
103
|
# Applies guards on the marking currently owned by the place.
|
@@ -0,0 +1,460 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
# Mixin that provides methods exposing place and transition collections to
|
4
|
+
# YPetri::Simulation.
|
5
|
+
#
|
6
|
+
class YPetri::Simulation
|
7
|
+
module Collections
|
8
|
+
# Returns the simulation's places. Optional arguments / block make it return
|
9
|
+
# a hash <tt>places => values</tt>, such as:
|
10
|
+
#
|
11
|
+
# places :marking
|
12
|
+
# #=> { <Place:Foo> => 42, <Place:Bar> => 43, ... }
|
13
|
+
#
|
14
|
+
def places *aa, &b
|
15
|
+
return @places.dup if aa.empty? && b.nil?
|
16
|
+
zip_to_hash places, *aa, &b
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the simulation's transitions. Optional arguments / block make it
|
20
|
+
# return a hash <tt>places => values</tt>, such as:
|
21
|
+
#
|
22
|
+
# transitions :flux
|
23
|
+
# #=> { <Transition:Baz> => 42, <Transition:Quux => 43, ... }
|
24
|
+
#
|
25
|
+
def transitions *aa, &b
|
26
|
+
return @transitions.dup if aa.empty? && b.nil?
|
27
|
+
zip_to_hash transitions, *aa, &b
|
28
|
+
end
|
29
|
+
|
30
|
+
# Like #places method, except that in the output, names are used instead of
|
31
|
+
# place instances when possible.
|
32
|
+
#
|
33
|
+
def pp *aa, &b
|
34
|
+
return places.map &:name if aa.empty? && b.nil?
|
35
|
+
zip_to_hash( places.map { |p| p.name || p }, *aa, &b )
|
36
|
+
end
|
37
|
+
|
38
|
+
# Like #transitions method, except that in the output, names are used
|
39
|
+
# instead of transition instances when possible.
|
40
|
+
#
|
41
|
+
def tt *aa, &b
|
42
|
+
return transitions.map &:name if aa.empty? && b.nil?
|
43
|
+
zip_to_hash( transitions.map { |t| t.name || t }, *aa, &b )
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the simulation's free places, with same syntax options as #places
|
47
|
+
# method.
|
48
|
+
#
|
49
|
+
def free_places *aa, &b
|
50
|
+
return zip_to_hash free_places, *aa, &b unless aa.empty? && b.nil?
|
51
|
+
kk = @initial_marking.keys
|
52
|
+
places.select { |p| kk.include? p }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Like #free_places, except that in the output, names are used instead of
|
56
|
+
# place instances when possible.
|
57
|
+
#
|
58
|
+
def free_pp *aa, &b
|
59
|
+
return free_places.map { |p| p.name || p } if aa.empty? && b.nil?
|
60
|
+
zip_to_hash free_pp, *aa, &b
|
61
|
+
end
|
62
|
+
|
63
|
+
# Initial marking definitions for free places (as array).
|
64
|
+
#
|
65
|
+
def im
|
66
|
+
free_places.map { |p| @initial_marking[p] }
|
67
|
+
end
|
68
|
+
|
69
|
+
# Marking array of all places as it appears at the beginning of a simulation.
|
70
|
+
#
|
71
|
+
def initial_marking
|
72
|
+
raise # FIXME: "Initial marking" for all places (ie. incl. clamped ones).
|
73
|
+
end
|
74
|
+
|
75
|
+
# Initial marking of free places (as column vector).
|
76
|
+
#
|
77
|
+
def im_vector
|
78
|
+
Matrix.column_vector im
|
79
|
+
end
|
80
|
+
alias iᴍ im_vector
|
81
|
+
|
82
|
+
# Marking of all places at the beginning of a simulation (as column vector).
|
83
|
+
#
|
84
|
+
def initial_marking_vector
|
85
|
+
Matrix.column_vector initial_marking
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the simulation's clamped places, with same syntax options as #places
|
89
|
+
# method.
|
90
|
+
#
|
91
|
+
def clamped_places *aa, &b
|
92
|
+
return zip_to_hash clamped_places, *aa, &b unless aa.empty? && b.nil?
|
93
|
+
kk = @marking_clamps.keys
|
94
|
+
places.select { |p| kk.include? p }
|
95
|
+
end
|
96
|
+
|
97
|
+
# Like #clamped_places, except that in the output, names are used instead of
|
98
|
+
# place instances whenever possible.
|
99
|
+
#
|
100
|
+
def clamped_pp *aa, &b
|
101
|
+
return clamped_places.map { |p| p.name || p } if aa.empty? && b.nil?
|
102
|
+
zip_to_hash clamped_pp, *aa, &b
|
103
|
+
end
|
104
|
+
|
105
|
+
# Place clamp definitions for clamped places (as array)
|
106
|
+
#
|
107
|
+
def marking_clamps
|
108
|
+
clamped_places.map { |p| @marking_clamps[p] }
|
109
|
+
end
|
110
|
+
alias place_clamps marking_clamps
|
111
|
+
|
112
|
+
# Marking of free places (as array).
|
113
|
+
#
|
114
|
+
def m
|
115
|
+
m_vector.column_to_a
|
116
|
+
end
|
117
|
+
|
118
|
+
# Marking of free places (as hash of pairs <tt>{ name: marking }</tt>).
|
119
|
+
#
|
120
|
+
def pm
|
121
|
+
free_pp :m
|
122
|
+
end
|
123
|
+
alias p_m pm
|
124
|
+
|
125
|
+
# Marking of free places (as hash of pairs <tt>{ place: marking }</tt>.
|
126
|
+
#
|
127
|
+
def place_m
|
128
|
+
free_places :m
|
129
|
+
end
|
130
|
+
|
131
|
+
# Marking of all places (as array).
|
132
|
+
#
|
133
|
+
def marking
|
134
|
+
marking_vector ? marking_vector.column_to_a : nil
|
135
|
+
end
|
136
|
+
|
137
|
+
# Marking of all places (as hash of pairs <tt>{ name: marking }</tt>).
|
138
|
+
#
|
139
|
+
def p_marking
|
140
|
+
pp :marking
|
141
|
+
end
|
142
|
+
alias pmarking p_marking
|
143
|
+
|
144
|
+
# Marking of all places (as hash of pairs <tt>{ place: marking }</tt>.
|
145
|
+
#
|
146
|
+
def place_marking
|
147
|
+
places :marking
|
148
|
+
end
|
149
|
+
|
150
|
+
# Marking of a specified place or a collection of places.
|
151
|
+
#
|
152
|
+
def marking_of places
|
153
|
+
m = place_marking
|
154
|
+
return places.map { |pl| m[ place( pl ) ] } if places.respond_to? :each
|
155
|
+
m[ place( place_or_places ) ]
|
156
|
+
end
|
157
|
+
alias m_of marking_of
|
158
|
+
|
159
|
+
# Marking of free places ( as column vector).
|
160
|
+
#
|
161
|
+
def m_vector
|
162
|
+
F2A().t * @marking_vector
|
163
|
+
end
|
164
|
+
alias ᴍ m_vector
|
165
|
+
|
166
|
+
# Marking of clamped places (as column vector).
|
167
|
+
#
|
168
|
+
def marking_vector_of_clamped_places
|
169
|
+
C2A().t * @marking_vector
|
170
|
+
end
|
171
|
+
alias ᴍ_clamped marking_vector_of_clamped_places
|
172
|
+
|
173
|
+
# Marking of clamped places (as array).
|
174
|
+
#
|
175
|
+
def marking_of_clamped_places
|
176
|
+
marking_vector_of_clamped_places.column( 0 ).to_a
|
177
|
+
end
|
178
|
+
alias m_clamped marking_of_clamped_places
|
179
|
+
|
180
|
+
# Returns a stoichiometry matrix for an arbitrary array of stoichiometric
|
181
|
+
# transitions. The returned stoichiometry matrix has the number of columns
|
182
|
+
# equal to the number of supplied stoichimetric transitions, and the number
|
183
|
+
# of rows equal to the number of free places. When multiplied by a vector
|
184
|
+
# corresponding to the transitions (such as flux vector), the resulting
|
185
|
+
# column vector corresponds to the free places.
|
186
|
+
#
|
187
|
+
def S_for( stoichiometric_transitions )
|
188
|
+
stoichiometric_transitions.map { |t| sparse_σ t }
|
189
|
+
.reduce( Matrix.empty( free_places.size, 0 ), :join_right )
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns a stoichiometry matrix for an arbitrary array of stoichiometric
|
193
|
+
# transitions. Behaves like +#S_for+ method, with the difference that the
|
194
|
+
# rows correspond to _all_ places, not just free places.
|
195
|
+
#
|
196
|
+
def stoichiometry_matrix_for( stoichiometric_transitions )
|
197
|
+
stoichiometric_transitions.map { |t| sparse_stoichiometry_vector t }
|
198
|
+
.reduce( Matrix.empty( places.size, 0 ), :join_right )
|
199
|
+
end
|
200
|
+
|
201
|
+
# Stoichiometry matrix of this simulation. By calling this method, the
|
202
|
+
# caller asserts, that all transitions in this simulation are SR transitions
|
203
|
+
# (or error).
|
204
|
+
#
|
205
|
+
def S
|
206
|
+
return S_SR() if s_transitions.empty? && r_transitions.empty?
|
207
|
+
raise "The simulation contains also non-stoichiometric transitions! " +
|
208
|
+
"Consider using #S_for_SR."
|
209
|
+
end
|
210
|
+
|
211
|
+
# ==== ts transitions
|
212
|
+
|
213
|
+
# Returns the simulation's *ts* transitions, with syntax options like
|
214
|
+
# #transitions method.
|
215
|
+
#
|
216
|
+
def ts_transitions *aa, &b
|
217
|
+
return zip_to_hash ts_transitions, *aa, &b unless aa.empty? && b.nil?
|
218
|
+
sift_from_net :ts_transitions
|
219
|
+
end
|
220
|
+
|
221
|
+
# Like #ts_transitions, except that in the output, names are used instead
|
222
|
+
# of instances when possible.
|
223
|
+
#
|
224
|
+
def ts_tt *aa, &b
|
225
|
+
return zip_to_hash ts_tt, *aa, &b unless aa.empty? && b.nil?
|
226
|
+
ts_transitions.map { |t| t.name || t }
|
227
|
+
end
|
228
|
+
|
229
|
+
# Returns the simulation's *non-assignment* *ts* transtitions, with syntax
|
230
|
+
# options like #transitions method. While *A* transitions can be regarded
|
231
|
+
# as a special kind of *ts* transitions, it may often be useful to separate
|
232
|
+
# them out from the collection of "ordinary" *ts* transtitions (*tsa*
|
233
|
+
# transitions).
|
234
|
+
#
|
235
|
+
def tsa_transitions *aa, &b
|
236
|
+
return zip_to_hash tsa_transitions, *aa, &b unless aa.empty? && b.nil?
|
237
|
+
sift_from_net :tsa_transitions
|
238
|
+
end
|
239
|
+
|
240
|
+
# Like #tsa_transitions, except that in the output, names are used instead
|
241
|
+
# of instances when possible.
|
242
|
+
#
|
243
|
+
def tsa_tt *aa, &b
|
244
|
+
return zip_to_hash tsa_tt, *aa, &b unless aa.empty? && b.nil?
|
245
|
+
tsa_transitions.map { |t| t.name || t }
|
246
|
+
end
|
247
|
+
|
248
|
+
# ==== tS transitions
|
249
|
+
|
250
|
+
# Returns the simulation's *tS* transitions, with syntax options like
|
251
|
+
# #transitions method.
|
252
|
+
#
|
253
|
+
def tS_transitions *aa, &b
|
254
|
+
return zip_to_hash tS_transitions, *aa, &b unless aa.empty? && b.nil?
|
255
|
+
sift_from_net :tS_transitions
|
256
|
+
end
|
257
|
+
|
258
|
+
# Like #tS_transitions, except that in the output, names are used instead
|
259
|
+
# of instances when possible.
|
260
|
+
#
|
261
|
+
def tS_tt *aa, &b
|
262
|
+
return zip_to_hash tS_tt, *aa, &b unless aa.empty? && b.nil?
|
263
|
+
tS_transitions.map { |t| t.name || t }
|
264
|
+
end
|
265
|
+
|
266
|
+
# ==== Tsr transitions
|
267
|
+
|
268
|
+
# Returns the simulation's *Tsr* transitions, with syntax options like
|
269
|
+
# #transitions method.
|
270
|
+
#
|
271
|
+
def Tsr_transitions *aa, &b
|
272
|
+
return zip_to_hash Tsr_transitions(), *aa, &b unless aa.empty? && b.nil?
|
273
|
+
sift_from_net :Tsr_transitions
|
274
|
+
end
|
275
|
+
|
276
|
+
# Like #Tsr_transitions, except that in the output, names are used instead
|
277
|
+
# of instances when possible.
|
278
|
+
#
|
279
|
+
def Tsr_tt *aa, &b
|
280
|
+
return zip_to_hash Tsr_tt(), *aa, &b unless aa.empty? && b.nil?
|
281
|
+
Tsr_transitions().map { |t| t.name || t }
|
282
|
+
end
|
283
|
+
|
284
|
+
# ==== TSr transitions
|
285
|
+
|
286
|
+
# Returns the simulation's *TSr* transitions, with syntax options like
|
287
|
+
# #transitions method.
|
288
|
+
#
|
289
|
+
def TSr_transitions *aa, &b
|
290
|
+
return zip_to_hash TSr_transitions(), *aa, &b unless aa.empty? && b.nil?
|
291
|
+
sift_from_net :TSr_transitions
|
292
|
+
end
|
293
|
+
|
294
|
+
# Like #TSr_transitions, except that in the output, names are used instead
|
295
|
+
# of instances when possible.
|
296
|
+
#
|
297
|
+
def TSr_tt *aa, &b
|
298
|
+
return zip_to_hash TSr_tt(), *aa, &b unless aa.empty? && b.nil?
|
299
|
+
TSr_transitions().map { |t| t.name || t }
|
300
|
+
end
|
301
|
+
|
302
|
+
# ==== sR transitions
|
303
|
+
|
304
|
+
# Returns the simulation's *sR* transitions, with syntax options like
|
305
|
+
# #transitions method.
|
306
|
+
#
|
307
|
+
def sR_transitions *aa, &b
|
308
|
+
return zip_to_hash sR_transitions(), *aa, &b unless aa.empty? && b.nil?
|
309
|
+
sift_from_net :sR_transitions
|
310
|
+
end
|
311
|
+
|
312
|
+
# Like #sR_transitions, except that in the output, names are used instead
|
313
|
+
# of instances when possible.
|
314
|
+
#
|
315
|
+
def sR_tt *aa, &b
|
316
|
+
return zip_to_hash sR_tt(), *aa, &b unless aa.empty? && b.nil?
|
317
|
+
sR_transitions.map { |t| t.name || t }
|
318
|
+
end
|
319
|
+
|
320
|
+
# ==== SR transitions
|
321
|
+
|
322
|
+
# Returns the simulation's *SR* transitions, with syntax options like
|
323
|
+
# #transitions method.
|
324
|
+
#
|
325
|
+
def SR_transitions *aa, &b
|
326
|
+
return zip_to_hash SR_transitions(), *aa, &b unless aa.empty? && b.nil?
|
327
|
+
sift_from_net :SR_transitions
|
328
|
+
end
|
329
|
+
|
330
|
+
# Like #SR_transitions, except that in the output, names are used instead
|
331
|
+
# of instances when possible.
|
332
|
+
#
|
333
|
+
def SR_tt *aa, &b
|
334
|
+
return zip_to_hash SR_tt(), *aa, &b unless aa.empty? && b.nil?
|
335
|
+
SR_transitions().map { |t| t.name || t }
|
336
|
+
end
|
337
|
+
|
338
|
+
# ==== Assignment (A) transitions
|
339
|
+
|
340
|
+
# Returns the simulation's *A* transitions, with syntax options like
|
341
|
+
# #transitions method.
|
342
|
+
#
|
343
|
+
def A_transitions *aa, &b
|
344
|
+
return zip_to_hash A_transitions(), *aa, &b unless aa.empty? && b.nil?
|
345
|
+
sift_from_net :A_transitions
|
346
|
+
end
|
347
|
+
alias assignment_transitions A_transitions
|
348
|
+
|
349
|
+
# Like #A_transitions, except that in the output, names are used instead
|
350
|
+
# of instances when possible.
|
351
|
+
#
|
352
|
+
def A_tt *aa, &b
|
353
|
+
return zip_to_hash A_tt(), *aa, &b unless aa.empty? && b.nil?
|
354
|
+
A_transitions().map { |t| t.name || t }
|
355
|
+
end
|
356
|
+
alias assignment_tt A_tt
|
357
|
+
|
358
|
+
# ==== Stoichiometric transitions of arbitrary type (S transitions)
|
359
|
+
|
360
|
+
# Returns the simulation's *S* transitions, with syntax options like
|
361
|
+
# #transitions method.
|
362
|
+
#
|
363
|
+
def S_transitions *aa, &b
|
364
|
+
return zip_to_hash S_transitions(), *aa, &b unless aa.empty? && b.nil?
|
365
|
+
sift_from_net :S_transitions
|
366
|
+
end
|
367
|
+
|
368
|
+
# Like #S_transitions, except that in the output, names are used instead
|
369
|
+
# of instances when possible.
|
370
|
+
#
|
371
|
+
def S_tt *aa, &b
|
372
|
+
return zip_to_hash S_tt(), *aa, &b unless aa.empty? && b.nil?
|
373
|
+
S_transitions().map { |t| t.name || t }
|
374
|
+
end
|
375
|
+
|
376
|
+
# ==== Nonstoichiometric transitions of arbitrary type (s transitions)
|
377
|
+
|
378
|
+
# Returns the simulation's *s* transitions, with syntax options like
|
379
|
+
# #transitions method.
|
380
|
+
#
|
381
|
+
def s_transitions *aa, &b
|
382
|
+
return zip_to_hash s_transitions, *aa, &b unless aa.empty? && b.nil?
|
383
|
+
sift_from_net :s_transitions
|
384
|
+
end
|
385
|
+
|
386
|
+
# Like #s_transitions, except that in the output, names are used instead
|
387
|
+
# of instances when possible.
|
388
|
+
#
|
389
|
+
def s_tt *aa, &b
|
390
|
+
return zip_to_hash s_tt, *aa, &b unless aa.empty? && b.nil?
|
391
|
+
s_transitions.map { |t| t.name || t }
|
392
|
+
end
|
393
|
+
|
394
|
+
# ==== Transitions with rate of arbitrary type (R transitions)
|
395
|
+
|
396
|
+
# Returns the simulation's *R* transitions, with syntax options like
|
397
|
+
# #transitions method.
|
398
|
+
#
|
399
|
+
def R_transitions *aa, &b
|
400
|
+
return zip_to_hash R_transitions(), *aa, &b unless aa.empty? && b.nil?
|
401
|
+
sift_from_net :R_transitions
|
402
|
+
end
|
403
|
+
|
404
|
+
# Like #R_transitions, except that in the output, names are used instead
|
405
|
+
# of instances when possible.
|
406
|
+
#
|
407
|
+
def R_tt *aa, &b
|
408
|
+
return zip_to_hash R_tt(), *aa, &b unless aa.empty? && b.nil?
|
409
|
+
R_transitions().map { |t| t.name || t }
|
410
|
+
end
|
411
|
+
|
412
|
+
# ==== Rateless transitions of arbitrary type (r transitions)
|
413
|
+
|
414
|
+
# Returns the simulation's *r* transitions, with syntax options like
|
415
|
+
# #transitions method.
|
416
|
+
#
|
417
|
+
def r_transitions *aa, &b
|
418
|
+
return zip_to_hash r_transitions, *aa, &b unless aa.empty? && b.nil?
|
419
|
+
sift_from_net :r_transitions
|
420
|
+
end
|
421
|
+
|
422
|
+
# Like #r_transitions, except that transition names are used instead of
|
423
|
+
# instances, whenever possible.
|
424
|
+
#
|
425
|
+
def r_tt *aa, &b
|
426
|
+
return zip_to_hash r_tt, *aa, &b unless aa.empty? && b.nil?
|
427
|
+
r_transitions.map { |t| t.name || t }
|
428
|
+
end
|
429
|
+
|
430
|
+
private
|
431
|
+
|
432
|
+
# This helper method takes a collection, a variable number of other arguments
|
433
|
+
# and an optional block, and returns a hash whose keys are the collection
|
434
|
+
# members, and whose values are given by the supplied othe arguments and/or
|
435
|
+
# block in the following way: If there is no additional argument, but a block
|
436
|
+
# is supplied, this is applied to the collection. If there is exactly one
|
437
|
+
# other argument, and it is also a collection, it is used as values.
|
438
|
+
# Otherwise, these other arguments are treated as a message to be sent to
|
439
|
+
# self (via #send), expecting it to return a collection to be used as hash
|
440
|
+
# values. Optional block (which is always assumed to be unary) can be used
|
441
|
+
# to additionally modify the second collection.
|
442
|
+
#
|
443
|
+
def zip_to_hash collection, *args, &block
|
444
|
+
sz = args.size
|
445
|
+
values = if sz == 0 then collection
|
446
|
+
elsif sz == 1 && args[0].respond_to?( :each ) then args[0]
|
447
|
+
else send *args end
|
448
|
+
Hash[ collection.zip( block ? values.map( &block ) : values ) ]
|
449
|
+
end
|
450
|
+
|
451
|
+
# Chicken approach towards ensuring that transitions in question come in
|
452
|
+
# the same order as in @transitions local variable. Takes a symbol as the
|
453
|
+
# argument (:SR, :TSr, :sr etc.)
|
454
|
+
#
|
455
|
+
def sift_from_net type_of_transitions
|
456
|
+
from_net = net.send type_of_transitions
|
457
|
+
@transitions.select { |t| from_net.include? t }
|
458
|
+
end
|
459
|
+
end # module Collections
|
460
|
+
end # class YPetri::Simulation
|