y_petri 2.2.4 → 2.3.2

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +675 -0
  3. data/README.md +6 -3
  4. data/Rakefile +1 -1
  5. data/lib/y_petri/agent/{petri_net_related.rb → petri_net_aspect.rb} +34 -10
  6. data/lib/y_petri/agent/{simulation_related.rb → simulation_aspect.rb} +49 -34
  7. data/lib/y_petri/agent.rb +5 -5
  8. data/lib/y_petri/core/guarded.rb +24 -0
  9. data/lib/y_petri/core/timed/euler.rb +4 -8
  10. data/lib/y_petri/core/timed/gillespie.rb +11 -17
  11. data/lib/y_petri/core/timed/methods.rb +23 -0
  12. data/lib/y_petri/core/timed/pseudo_euler.rb +10 -13
  13. data/lib/y_petri/core/timed/quasi_euler.rb +9 -8
  14. data/lib/y_petri/core/timed/runge_kutta.rb +10 -18
  15. data/lib/y_petri/core/timed.rb +6 -14
  16. data/lib/y_petri/core/timeless/methods.rb +15 -0
  17. data/lib/y_petri/core/timeless/pseudo_euler.rb +4 -8
  18. data/lib/y_petri/core/timeless.rb +9 -4
  19. data/lib/y_petri/core.rb +44 -42
  20. data/lib/y_petri/net/data_set.rb +246 -142
  21. data/lib/y_petri/net/node_access.rb +282 -0
  22. data/lib/y_petri/net/own_state.rb +14 -4
  23. data/lib/y_petri/net/state/feature/assignment.rb +123 -0
  24. data/lib/y_petri/net/state/feature/delta.rb +55 -35
  25. data/lib/y_petri/net/state/feature/firing.rb +68 -25
  26. data/lib/y_petri/net/state/feature/flux.rb +9 -2
  27. data/lib/y_petri/net/state/feature/gradient.rb +36 -19
  28. data/lib/y_petri/net/state/feature/marking.rb +10 -5
  29. data/lib/y_petri/net/state/feature.rb +105 -11
  30. data/lib/y_petri/net/state/features/record.rb +144 -99
  31. data/lib/y_petri/net/state/features.rb +327 -200
  32. data/lib/y_petri/net/state.rb +48 -82
  33. data/lib/y_petri/net/visualization.rb +1 -1
  34. data/lib/y_petri/net.rb +62 -47
  35. data/lib/y_petri/place/arcs.rb +44 -0
  36. data/lib/y_petri/place/features.rb +115 -0
  37. data/lib/y_petri/place.rb +62 -29
  38. data/lib/y_petri/simulation/dependency.rb +31 -67
  39. data/lib/y_petri/simulation/feature_set.rb +1 -1
  40. data/lib/y_petri/simulation/initial_marking/access.rb +42 -26
  41. data/lib/y_petri/simulation/marking_clamps/access.rb +22 -17
  42. data/lib/y_petri/simulation/marking_clamps.rb +0 -2
  43. data/lib/y_petri/simulation/marking_vector/access.rb +102 -40
  44. data/lib/y_petri/simulation/marking_vector.rb +35 -37
  45. data/lib/y_petri/simulation/matrix.rb +1 -1
  46. data/lib/y_petri/simulation/node_representation.rb +25 -0
  47. data/lib/y_petri/simulation/nodes/access.rb +78 -0
  48. data/lib/y_petri/simulation/{elements.rb → nodes.rb} +14 -13
  49. data/lib/y_petri/simulation/place_mapping.rb +2 -2
  50. data/lib/y_petri/simulation/place_representation.rb +8 -7
  51. data/lib/y_petri/simulation/places/access.rb +89 -70
  52. data/lib/y_petri/simulation/places/free.rb +1 -1
  53. data/lib/y_petri/simulation/places/types.rb +20 -22
  54. data/lib/y_petri/simulation/places.rb +23 -18
  55. data/lib/y_petri/simulation/recorder.rb +23 -18
  56. data/lib/y_petri/simulation/timed/recorder.rb +19 -11
  57. data/lib/y_petri/simulation/timed.rb +93 -29
  58. data/lib/y_petri/simulation/timeless/recorder.rb +11 -6
  59. data/lib/y_petri/simulation/timeless.rb +13 -3
  60. data/lib/y_petri/simulation/transition_representation/A.rb +24 -4
  61. data/lib/y_petri/simulation/transition_representation/S.rb +11 -1
  62. data/lib/y_petri/simulation/transition_representation/T.rb +1 -1
  63. data/lib/y_petri/simulation/transition_representation/Ts.rb +1 -1
  64. data/lib/y_petri/simulation/transition_representation/a.rb +1 -1
  65. data/lib/y_petri/simulation/transition_representation/s.rb +12 -1
  66. data/lib/y_petri/simulation/transition_representation/t.rb +1 -1
  67. data/lib/y_petri/simulation/transition_representation/tS.rb +1 -1
  68. data/lib/y_petri/simulation/transition_representation/ts.rb +1 -1
  69. data/lib/y_petri/simulation/transition_representation/types.rb +1 -1
  70. data/lib/y_petri/simulation/transition_representation.rb +4 -11
  71. data/lib/y_petri/simulation/transitions/A.rb +17 -2
  72. data/lib/y_petri/simulation/transitions/S.rb +1 -1
  73. data/lib/y_petri/simulation/transitions/T.rb +1 -1
  74. data/lib/y_petri/simulation/transitions/Ts.rb +6 -5
  75. data/lib/y_petri/simulation/transitions/a.rb +1 -1
  76. data/lib/y_petri/simulation/transitions/access.rb +195 -168
  77. data/lib/y_petri/simulation/transitions/s.rb +1 -1
  78. data/lib/y_petri/simulation/transitions/t.rb +1 -1
  79. data/lib/y_petri/simulation/transitions/tS.rb +1 -1
  80. data/lib/y_petri/simulation/transitions/ts.rb +1 -1
  81. data/lib/y_petri/simulation/transitions/types.rb +1 -1
  82. data/lib/y_petri/simulation/transitions.rb +5 -7
  83. data/lib/y_petri/simulation.rb +84 -90
  84. data/lib/y_petri/transition/A.rb +8 -2
  85. data/lib/y_petri/transition/T.rb +25 -2
  86. data/lib/y_petri/transition/arcs.rb +19 -3
  87. data/lib/y_petri/transition/construction_convenience.rb +11 -10
  88. data/lib/y_petri/transition/t.rb +14 -1
  89. data/lib/y_petri/transition/types.rb +6 -1
  90. data/lib/y_petri/transition.rb +9 -12
  91. data/lib/y_petri/version.rb +1 -1
  92. data/lib/y_petri/world/dependency.rb +3 -3
  93. data/lib/y_petri/world/{petri_net_related.rb → petri_net_aspect.rb} +4 -4
  94. data/lib/y_petri/world/simulation_aspect.rb +352 -0
  95. data/lib/y_petri/world.rb +4 -4
  96. data/lib/y_petri.rb +1 -1
  97. data/test/agent_test.rb +2 -1
  98. data/test/examples/demonstrator.rb +4 -1
  99. data/test/examples/demonstrator_2.rb +5 -0
  100. data/test/examples/demonstrator_4.rb +6 -5
  101. data/test/examples/example_2.rb +2 -0
  102. data/test/examples/manual_examples.rb +4 -4
  103. data/test/net_test.rb +457 -54
  104. data/test/place_test.rb +11 -7
  105. data/test/simulation_test.rb +358 -331
  106. data/test/transition_test.rb +11 -10
  107. data/test/world_test.rb +2 -0
  108. data/test/y_petri_test.rb +2 -1
  109. data/y_petri.gemspec +24 -18
  110. metadata +71 -17
  111. data/LICENSE +0 -22
  112. data/lib/y_petri/net/element_access.rb +0 -239
  113. data/lib/y_petri/simulation/element_representation.rb +0 -20
  114. data/lib/y_petri/simulation/elements/access.rb +0 -57
  115. data/lib/y_petri/transition/type.rb +0 -103
  116. data/lib/y_petri/transition/type_information.rb +0 -103
  117. data/lib/y_petri/world/simulation_related.rb +0 -176
@@ -20,160 +20,263 @@ class YPetri::Net::State::Features < Array
20
20
  end
21
21
  end
22
22
 
23
- delegate :net,
24
- :Feature,
25
- :feature,
26
- to: "State()"
27
-
28
- delegate :Marking,
29
- :Firing,
30
- :Gradient,
31
- :Flux,
32
- :Delta,
33
- to: "Feature()"
34
-
23
+ delegate :net, to: "State()"
35
24
  delegate :load, to: "Record()"
36
25
 
37
26
  alias __new__ new
38
27
 
39
28
  def new features
40
- array = features.map &method( :feature )
41
- __new__( array ).tap do |inst|
29
+ features = features.map &State().method( :Feature )
30
+ __new__( features ).tap do |inst|
42
31
  # Parametrize them <em>one more time</em> with Features instance.
43
32
  # Banged version of #param_class! ensures that #Record, #Dataset
44
33
  # methods are shadowed.
45
- inst.param_class!( { Record: Record(), DataSet: DataSet() },
34
+ inst.param_class!( { Record: Record(),
35
+ DataSet: DataSet() },
46
36
  with: { features: inst } )
47
37
  end
48
38
  end
49
39
 
50
- # Takes an array of marking feature identifiers (places, Marking instances),
51
- # and returns the corresponding array of marking features valid for the
52
- # current net. If no argument is given, an array of all the marking features
53
- # of the current net is returned.
40
+ # Takes an arbitrary number of ordered arguments identifying features, or
41
+ # named arguments +:marking+, +:firing+, +:gradient+, +:flux+, +:delta+,
42
+ # +:assignment+ containing arrays identifying the corresponding type of
43
+ # features.
54
44
  #
55
- def marking arg=nil
56
- return marking net.pp if arg.nil?
57
- new arg.map { |id| Marking id }
45
+ def [] *ordered_args, **named_args
46
+ unless ordered_args.empty?
47
+ fail ArgumentError, "Named arguments must not be given if ordered " +
48
+ "arguments are given!" unless named_args.empty?
49
+ return infer_from_nodes( ordered_args )
50
+ end
51
+ a = []
52
+ a << Marking( Array named_args[ :marking ] ) if named_args[ :marking ]
53
+ a << Firing( Array named_args[ :firing ] ) if named_args[ :firing ]
54
+ a << Flux( Array named_args[ :flux ] ) if named_args[ :flux ]
55
+ if named_args[ :gradient ] then
56
+ ordered = Array( named_args[ :gradient ] )
57
+ named = ordered.extract_options!
58
+ a << Gradient( ordered, **named )
59
+ end
60
+ if named_args[ :delta ] then
61
+ ordered = Array( named_args[ :delta ] )
62
+ named = ordered.extract_options!
63
+ a << Delta( ordered, **named )
64
+ end
65
+ if named_args[ :assignment ] then
66
+ ordered = Array( named_args[ :assignment ] )
67
+ named = ordered.extract_options!
68
+ a << Assignment( ordered, **named )
69
+ end
70
+ a.size == 1 ? a.first : a.reduce( new( [] ), :+ )
58
71
  end
59
72
 
60
- # Takes an array of firing feature identifiers (transitions, Firing
61
- # instances), and returns the corresponding array of firing features valid
62
- # for the current net. If no argument is given, an array of all the firing
63
- # features of the current net is returned.
73
+ # Constructs a set of marking features from an array of marking feature
74
+ # identifiers.
64
75
  #
65
- def firing arg=nil
66
- return firing net.tS_tt if arg.nil?
67
- new arg.map { |id| Firing id }
76
+ def Marking array
77
+ new array.map &net.State.Feature.method( :Marking )
68
78
  end
69
79
 
70
- # Takes an array of gradient feature identifiers (places, Marking instances),
71
- # qualified by an array of transitions (named argument +:transitions+,
72
- # defaults to all the timed transitions in the net), and returns the
73
- # corresponding array of gradient features valid for the current net. If no
74
- # argument is given, an array of all the gradient features qualified by the
75
- # +:transitions+ argument is returned.
80
+ # Expects an arbitrary number of marking feature identifiers and constructs
81
+ # a feature set out of them. Without arguments, full marking feature set
82
+ # for the underlying net is returned.
76
83
  #
77
- def gradient arg=nil, transitions: nil
78
- if arg.nil? then
79
- return gradient net.pp, transitions: net.T_tt if transitions.nil?
80
- gradient net.pp, transitions: transitions
81
- else
82
- return new arg.map { |id| Gradient id } if transitions.nil?
83
- new arg.map { |id| Gradient id, transitions: transitions }
84
- end
84
+ def marking *marking_feature_identifiers
85
+ return Marking net.pp if marking_feature_identifiers.empty?
86
+ Marking marking_feature_identifiers
87
+ end
88
+
89
+ # Constructs a set of firing features from an array of firing feature
90
+ # identifiers.
91
+ #
92
+ def Firing array, **named_args
93
+ new array.map &net.State.Feature.method( :Firing )
85
94
  end
86
95
 
87
- # Takes an array of flux feature identifiers (transitions, Flux instances),
88
- # and returns the corresponding array of flux features valid for the current
89
- # net. If no argument is given, an array of all the flux features of the
90
- # current net is returned.
96
+ # Expects an arbitrary number of firing feature identifiers and constructs
97
+ # a feature set out of them. Without arguments, full firing feature set
98
+ # (all S transitions) for the underlying net is returned.
91
99
  #
92
- def flux arg=nil
93
- return flux net.TS_tt if arg.nil?
94
- new arg.map { |t| Flux t }
100
+ def firing *firing_feature_identifiers
101
+ return Firing net.S_tt if firing_feature_identifiers.empty?
102
+ Firing firing_feature_identifiers
95
103
  end
96
104
 
97
- # Takes an array of delta feature identifiers (places, Delta instances),
98
- # qualified by an array of transitions (named argument +:transitions+,
99
- # defaults to all the transitions in the net), and returns the corresponding
100
- # array of delta features valid for the current net. If no argument is
101
- # given, an array of all the delta features qualified by the +:transitions+
102
- # argument is returned.
105
+ # Constructs a set of gradient features from an array of gradient feature
106
+ # identifiers, optionally qualified by an array of transitions supplied via
107
+ # the named argument +:transitions+.
103
108
  #
104
- def delta arg=nil, transitions: nil
105
- if arg.nil? then
106
- return delta net.pp, transitions: net.tt if transitions.nil?
107
- delta net.pp, transitions: transitions
109
+ def Gradient array, transitions: nil
110
+ return new array.map &net.State.Feature.method( :Gradient ) if
111
+ transitions.nil?
112
+ ary = array.map { |id|
113
+ net.State.Feature.Gradient id, transitions: transitions
114
+ }
115
+ new ary
116
+ end
117
+
118
+ # Expects an arbitrary number of gradient feature identifiers and constructs
119
+ # a feature set out of them, optionally qualified by an array of transitions
120
+ # supplied via the named argument +:transitions+. Returns the corresponding
121
+ # feature set. Without ordered arguments, full gradient feature set for the
122
+ # underlying net is returned.
123
+ #
124
+ def gradient *args, transitions: nil
125
+ return Gradient args, transitions: transitions unless args.empty?
126
+ return Gradient net.pp, transitions: net.T_tt if transitions.nil?
127
+ Gradient net.pp, transitions: transitions
128
+ end
129
+
130
+ # Constructs a set of flux features from an array of flux feature
131
+ # identifiers.
132
+ #
133
+ def Flux array
134
+ new array.map &net.State.Feature.method( :Flux )
135
+ end
136
+
137
+ # Expects an arbitrary number of flux feature identifiers and constructs
138
+ # a feature set out of them. Without arguments, full flux feature set for
139
+ # the underlying net is returned.
140
+ #
141
+ def flux *flux_feature_identifiers
142
+ return Flux net.TS_tt if flux_feature_identifiers.empty?
143
+ Flux flux_feature_identifiers
144
+ end
145
+
146
+ # Constructs a set of delta features from an array of delta feature
147
+ # identifiers, optionally qualified by an array of transitions supplied via
148
+ # the named argument +:transitions+.
149
+ #
150
+ def Delta array, transitions: nil
151
+ return new array.map &net.State.Feature.method( :Delta ) if
152
+ transitions.nil?
153
+ new array.map { |id|
154
+ net.State.Feature.Delta id, transitions: transitions
155
+ }
156
+ end
157
+
158
+ # Expects an arbitrary number of delta feature identifiers and constructs
159
+ # a feature set out of them, optionally qualified by an array of transitions
160
+ # supplied via the named argument +:transitions+. Returns the corresponding
161
+ # feature set. Without ordered arguments, full delta feature set for the
162
+ # underlying net is returned.
163
+ #
164
+ def delta *args, transitions: L!
165
+ return Delta args, transitions: transitions unless args.empty?
166
+ fail ArgumentError, "Sorry, but feature set constructor Features.delta " +
167
+ "cannot be used without :transitions named argument, because it is " +
168
+ "ambiguous whether the transition set should default to the timed or " +
169
+ "timeless transitions (they cannot be mixed together when " +
170
+ "constructing a delta feature). Please specify the transitions, or " +
171
+ "disambiguate timedness by using either .delta_timed or " +
172
+ ".delta_timeless method " if transitions.local_object?
173
+ Delta net.pp, transitions: transitions
174
+ end
175
+
176
+ # Expects an arbitrary number of place idetifiers and constructs a feature
177
+ # set out of them, optionally qualified by an array of T transitions supplied
178
+ # via the named argument +:transitions+. Returns the corresponding feature
179
+ # set. Without ordered arguments, full delta feature set for the underlying
180
+ # net is returned. If no transitions are supplied, full set of T transitions
181
+ # is assumed.
182
+ #
183
+ def delta_timed *args, transitions: L!
184
+ return delta *args, transitions: net.T_transitions if
185
+ transitions.local_object?
186
+ delta *args, transitions: net.T_Transitions( Array( transitions ) )
187
+ end
188
+
189
+ # Expects an arbitrary number of place idetifiers and constructs a feature
190
+ # set out of them, optionally qualified by an array of t (timeless)
191
+ # transitions supplied via the named argument +:transitions+. Returns the
192
+ # corresponding feature set. Without ordered arguments, full delta feature
193
+ # set for the underlying net is returned. If no transitions are supplied,
194
+ # full set of t (timeless) transitions is assumed.
195
+ #
196
+ def delta_timeless *args, transitions: L!
197
+ return delta *args, transitions: net.t_transitions if
198
+ transitions.local_object?
199
+ delta *args, transitions: net.t_Transitions( Array( transitions ) )
200
+ end
201
+
202
+ # Constructs a set of assignment features from an array of assignment feature
203
+ # identifiers.
204
+ #
205
+ def Assignment array, transition: L!
206
+ if transition.local_object? then
207
+ new array.map &net.State.Feature.method( :Assignment )
108
208
  else
109
- return new arg.map { |id| Delta id } if transitions.nil?
110
- new arg.map { |id| Delta id, transitions: transitions }
209
+ new array.map { |id|
210
+ net.State.Feature.Assignment id, transition: transition
211
+ }
111
212
  end
112
213
  end
113
214
 
114
- # Takes an array of the net elements (places and/or transitions), and infers
115
- # a feature set from them in the following way: Places or place ids are
116
- # converted to marking features. The remaining array elements are treated
117
- # as transition ids, and are converted to either flux features (if the
118
- # transition is timed), or firing features (if the transition is timeless).
215
+ # Expects an arbitrary number of assignment feature identifiers and
216
+ # constructs a feature set out of them.
119
217
  #
120
- def infer_from_elements( net_elements )
121
- new net_elements.map { |e| net.element( e ) }.map { |e|
122
- element, element_type = case e
123
- when Feature() then [ e, :feature ]
124
- else
125
- begin
126
- [ net.place( e ), :place ]
127
- rescue TypeError, NameError
128
- [ net.transition( e ), :transition ]
129
- end
130
- end
131
- case element_type
132
- when :feature then element
133
- when :place then Marking( element )
134
- when :transition then
135
- fail TypeError, "Flux / firing features can only be auto-inferred " +
136
- "from S transitions! (#{element} was given)" unless element.S?
137
- element.timed? ? Flux( element ) : Firing( element )
138
- end
218
+ def assignment *ids, transition: L!
219
+ if transition.local_object? then
220
+ fail ArgumentError, "Sorry, but Features.assignment method cannot " +
221
+ "be called without arguments. There is a convenience method " +
222
+ "Features.aa available, returning all the assignment features " +
223
+ "for the places with exactly one A transition upstream, if that." +
224
+ "is what you mean." if ids.empty?
225
+ Assignment( ids )
226
+ else
227
+ return Assignment( ids, transition: transition ) unless ids.empty?
228
+ Assignment net.transition( transition ).codomain, transition: transition
229
+ end
230
+ end
231
+
232
+ # Convenience method that returns the full set of assignment features
233
+ # for those places, which have exactly one A transition in their upstream
234
+ # arcs.
235
+ #
236
+ def aa
237
+ Assignment net.places.select { |p|
238
+ upstream = p.upstream_arcs
239
+ upstream.size == 1 && upstream.first.A?
139
240
  }
140
241
  end
141
- end
142
242
 
143
- delegate :State,
144
- :net,
145
- :Feature,
146
- :feature,
147
- :Marking,
148
- :Firing,
149
- :Gradient,
150
- :Flux,
151
- :Delta,
152
- to: "self.class"
243
+ # Takes an array of the net's nodes, and infers a feature set from them as
244
+ # follows: Places or place ids are converted to marking features. Remaining
245
+ # array elements are treated as transition ids, and are converted to either
246
+ # flux features (if the transition is timed), or firing features (if the
247
+ # transition is timeless).
248
+ #
249
+ def infer_from_nodes( nodes )
250
+ new nodes.map &net.State.Feature.method( :infer_from_node )
251
+ end
252
+ end
153
253
 
154
- delegate :load,
155
- to: "Record()"
254
+ delegate :net, to: "self.class"
156
255
 
157
- alias new_record load
256
+ delegate :load, to: "Record()" # Beware! #Record instance method returns
257
+ # a double parametrized subclass not identical
258
+ # to the one available via #Record class method.
158
259
 
159
- # Extracts the features from a given target, returning a +Record+ instance.
260
+ # Note that this method expects a single array argument. Message +:Record+
261
+ # without arguments is intercepted by a singleton method.
160
262
  #
161
- def extract_from target, **nn
162
- values = map { |feat| feat.extract_from( target, **nn ) }
163
- new_record( values )
164
- end
263
+ alias Record load
165
264
 
166
- # Constructs a new +Record+ instance from the supplied values array. The
167
- # values in the array must correspond to the receiver feature set.
265
+ # Extracts the features from a given target, returning a record.
168
266
  #
169
- def new_record values
170
- Record().load values
267
+ def extract_from target, **nn
268
+ values = map { |feature| feature.extract_from( target, **nn ) }
269
+ Record( values )
171
270
  end
172
271
 
173
- # Constructs a new dataset based on the receiver feature set.
272
+ # Interpolation operator +%+ acts as an alias for the +#extract_from+ feature
273
+ # extraction method.
174
274
  #
175
- def new_dataset *args, &blk
176
- DataSet().new *args, &blk
275
+ def % operand
276
+ args = Array( operand )
277
+ named_args = args.extract_options!
278
+ arg = args.first
279
+ extract_from arg, **named_args
177
280
  end
178
281
 
179
282
  # Summation of feature sets.
@@ -210,113 +313,137 @@ class YPetri::Net::State::Features < Array
210
313
  end
211
314
  end
212
315
 
213
- # Returns the subset of marking features.
214
-
215
- # Expects a marking feature identifier (place identifier or Marking instance),
216
- # and returns the corresponding feature from this feature set. If an array of
217
- # marking feature identifiers is supplied, it is mapped to the array of
218
- # corresponding features from this feature set. If no argument is given, all
219
- # the marking features from this set are returned.
220
- #
221
- def marking arg=nil
222
- return marking( select { |feat| feat.is_a? Marking() } ) if arg.nil?
223
- case arg
224
- when Array then self.class.new( arg.map { |id| marking id } )
225
- else
226
- Marking( arg ).tap do |feature|
227
- include? feature or
228
- fail KeyError, "No marking feature '#{arg}' in this feature set!"
316
+ # Returns a subset of marking features selected from this feature set. Expects
317
+ # a single array argument.
318
+ #
319
+ def Marking array
320
+ array = array.map do |id|
321
+ net.State.Feature.Marking( id ).tap do |f|
322
+ include? f or fail KeyError, "No marking feature '#{f}' in this set!"
229
323
  end
230
324
  end
325
+ self.class.new array
231
326
  end
232
327
 
233
- # Expects a firing feature idenfier (tS transition identifier, or Firing
234
- # instance), and returns the corresponding feature from this feature set. If
235
- # an array of firing feature identifiers is supplied, it is mapped to the
236
- # array of corresponding features from this feature set. If no argument is
237
- # given, all the firing features from this set are returned.
238
- #
239
- def firing arg=nil
240
- return firing( select { |feat| feat.is_a? Firing() } ) if arg.nil?
241
- case arg
242
- when Array then self.class.new( arg.map { |id| firing id } )
243
- else
244
- Firing( arg ).tap do |feature|
245
- include? feature or
246
- fail KeyError, "No firing feature '#{arg}' in this feature set!"
328
+ # Returns a subset of marking features selected from this feature set. Expects
329
+ # an arbitrary number of arguments. Without arguments, selects all of them.
330
+ #
331
+ def marking *ids
332
+ return Marking ids unless ids.empty?
333
+ self.class.new select { |f| f.is_a? net.State.Feature.Marking }
334
+ end
335
+
336
+ # Returns a subset of firing features selected from this feature set. Expects
337
+ # a single array argument.
338
+ #
339
+ def Firing array
340
+ self.class.new array.map { |id|
341
+ net.State.Feature.Firing( id ).tap do |f|
342
+ include? f or fail KeyError, "No firing feature '#{f}' in this set!"
247
343
  end
248
- end
344
+ }
249
345
  end
250
346
 
251
- # Expects a flux feature identifier (TS transition identifier, or Flux
252
- # instance), and returns the corresponding feature from this feature set. If
253
- # an array of flux feature identifiers is supplied, it is mapped to the array
254
- # of corresponding features from this feature set. If no argument is given,
255
- # all the flux features from this set are returned.
256
- #
257
- def flux arg=nil
258
- return flux( select { |feat| feat.is_a? Flux() } ) if arg.nil?
259
- case arg
260
- when Array then self.class.new( arg.map { |id| flux id } )
261
- else
262
- Flux( arg ).tap do |feature|
263
- include? feature or
264
- fail KeyError, "No flux feature '#{arg}' in this feature set!"
347
+ # Returns a subset of firing features selected from this feature set. Expects
348
+ # an arbitrary number of arguments. Without arguments, selects all of them.
349
+ #
350
+ def firing *ids
351
+ return Firing ids unless ids.empty?
352
+ self.class.new select { |f| f.is_a? net.State.Feature.Firing }
353
+ end
354
+
355
+ # Returns a subset of flux features selected from this feature set. Expects
356
+ # a single array argument.
357
+ #
358
+ def Flux array
359
+ self.class.new array.map { |id|
360
+ net.State.Feature.Flux( id ).tap do |f|
361
+ include? f or fail KeyError, "No flux feature '#{f}' in this set!"
265
362
  end
363
+ }
364
+ end
365
+
366
+ # Returns a subset of flux features selected from this feature set. Expects
367
+ # an arbitrary number of arguments. Without arguments, selects all of them.
368
+ #
369
+ def flux *ids
370
+ return Flux ids unless ids.empty?
371
+ self.class.new select { |f| f.is_a? net.State.Feature.Flux }
372
+ end
373
+
374
+ # Returns a subset of gradient features selected from this feature set.
375
+ # Expects a single array argument, optionally qualified by +:transitions+
376
+ # named argument, defaulting to all T transitions in the net.
377
+ #
378
+ def Gradient array, transitions: nil
379
+ self.class.new array.map { |id|
380
+ net.State.Feature.Gradient( id, transitions: transitions ).tap do |f|
381
+ include? f or fail KeyError, "No flux feature '#{f}' in this set!"
382
+ end
383
+ }
384
+ end
385
+
386
+ # Returns a subset of gradient features selected from this feature set.
387
+ # Expects an arbitrary number of arguments, optionally qualified by
388
+ # +:transitions+ named argument, defaulting to all T transitions in the
389
+ # net. Without arguments, selects all of them.
390
+ #
391
+ def gradient *ids, transitions: L!
392
+ return Gradient ids, transitions: transitions unless ids.empty?
393
+ if transitions.local_object? then
394
+ self.class.new select { |f| f.is_a? net.State.Feature.Gradient }
395
+ else
396
+ self.class.new select { |f| f.transitions == net.tt( Array transitions ) }
266
397
  end
267
398
  end
268
399
 
269
- # Expects a gradient feature identifier (place identifier, or Gradient
270
- # instance), qualified by an array of transitions (named argument
271
- # +:transitions+, defaults to all timed transitions in the net), and
272
- # returns the corresponding feature from this feature set. If an array of
273
- # gradient feature identifiers is supplied, it is mapped to the array of
274
- # corresponding features from this feature set. If no argument is given,
275
- # all the gradient features from this feature set are returned.
400
+ # Returns a subset of delta features selected from this feature set.
401
+ # Expects a single array argument, optionally qualified by +:transitions+
402
+ # named argument, defaulting to all the transitions in the net.
276
403
  #
277
- def gradient arg=nil, transitions: nil
278
- if arg.nil? then
279
- return gradient( select { |feat| feat.is_a? Gradient() } ) if
280
- transitions.nil?
281
- gradient.select { |feat| feat.transitions == net.tt( transitions ) }
282
- else
283
- case arg
284
- when Array then
285
- self.class.new( arg.map { |id| gradient id, transitions: transitions } )
286
- else
287
- Gradient( arg, transitions: transitions ).tap do |feature|
288
- include? feature or
289
- fail KeyError, "No gradient feature '#{arg}' in this fature set!"
290
- end
291
- end
292
- end
404
+ def Delta array, transitions: nil
405
+ self.class.new array.map { |id|
406
+ net.State.Feature.Delta( id, transitions: transitions ).tap do |f|
407
+ include? f or
408
+ fail KeyError, "No delta feature '#{f}' in this feature set!"
409
+ end
410
+ }
293
411
  end
294
412
 
295
- # Expects a delta feature identifier (place identifier, or Gradient instance),
296
- # qualified by an array of transitions (named argument +:transitions+,
297
- # defaulting to all the transtitions in the net), and returns the
298
- # corresponding feature from this feature set. If an array of delta feature
299
- # identifiers is supplied, it is mapped to the array of corresponding features
300
- # from thie feature set.
413
+ # Returns a subset of delta features selected from this feature set.
414
+ # Expects an arbitrary number of arguments, optionally qualified by
415
+ # +:transitions+ named argument, defaulting to all the transitions in the
416
+ # net. Without arguments, selects all the delta features.
301
417
  #
302
- def delta arg=nil, transitions: nil
303
- if arg.nil? then
304
- return delta( select { |feat| feat.is_a? Delta() } ) if
305
- transitions.nil?
306
- delta.select { |feat| feat.transitions == net.tt( transitions ) }
418
+ def delta *ids, transitions: L!
419
+ return Delta ids, transitions: transitions unless ids.empty?
420
+ if transitions.local_object? then
421
+ self.class.new select { |f| f.is_a? net.State.Feature.Delta }
307
422
  else
308
- case arg
309
- when Array then
310
- self.class.new( arg.map { |id| delta id, transitions: transitions } )
311
- else
312
- Delta( arg, transitions: transitions ).tap do |feature|
313
- include? feature or
314
- fail KeyError, "No delta feature '#{arg}' in this feature set!"
315
- end
316
- end
423
+ self.class.new select { |f| f.transitions == net.tt( Array transitions ) }
317
424
  end
318
425
  end
319
426
 
427
+ # Returns a subset of assignment features selected from this feature set.
428
+ # Expects a single array argument.
429
+ #
430
+ def Assignment array
431
+ self.class.new array.map { |id|
432
+ net.State.Feature.Assignment( id ).tap do |f|
433
+ include? f or fail KeyError, "No flux feature '#{f}' in this set!"
434
+ end
435
+ }
436
+ end
437
+
438
+ # Returns a subset of assignment features selected from this feature set.
439
+ # Expects an arbitrary number of arguments. Without arguments, selects all
440
+ # of them.
441
+ #
442
+ def assignment *ids
443
+ return Assignment ids unless ids.empty?
444
+ self.class.new select { |f| f.is_a? net.State.Feature.Assignment }
445
+ end
446
+
320
447
  # Returns a string briefly describing the feature set.
321
448
  #
322
449
  def to_s