y_petri 2.2.4 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
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