y_petri 2.0.15 → 2.1.3

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/lib/y_petri/{manipulator → agent}/hash_key_pointer.rb +2 -2
  3. data/lib/y_petri/agent/petri_net_related.rb +115 -0
  4. data/lib/y_petri/{manipulator → agent}/selection.rb +2 -1
  5. data/lib/y_petri/{manipulator/simulation_related_methods.rb → agent/simulation_related.rb} +93 -110
  6. data/lib/y_petri/agent.rb +22 -0
  7. data/lib/y_petri/core/timed/euler.rb +20 -0
  8. data/lib/y_petri/core/timed/pseudo_euler.rb +31 -0
  9. data/lib/y_petri/core/timed/quasi_euler.rb +23 -0
  10. data/lib/y_petri/core/timed.rb +70 -0
  11. data/lib/y_petri/core/timeless/pseudo_euler.rb +20 -0
  12. data/lib/y_petri/core/timeless.rb +12 -0
  13. data/lib/y_petri/core.rb +100 -0
  14. data/lib/y_petri/dsl.rb +66 -0
  15. data/lib/y_petri/fixed_assets.rb +7 -0
  16. data/lib/y_petri/net/element_access.rb +239 -0
  17. data/lib/y_petri/net/state/feature/delta.rb +88 -0
  18. data/lib/y_petri/net/state/feature/firing.rb +57 -0
  19. data/lib/y_petri/net/state/feature/flux.rb +58 -0
  20. data/lib/y_petri/net/state/feature/gradient.rb +75 -0
  21. data/lib/y_petri/net/state/feature/marking.rb +62 -0
  22. data/lib/y_petri/net/state/feature.rb +79 -0
  23. data/lib/y_petri/net/state/features/dataset.rb +135 -0
  24. data/lib/y_petri/net/state/features/record.rb +50 -0
  25. data/lib/y_petri/net/state/features.rb +126 -0
  26. data/lib/y_petri/net/state.rb +121 -0
  27. data/lib/y_petri/net/timed.rb +8 -0
  28. data/lib/y_petri/net/visualization.rb +3 -3
  29. data/lib/y_petri/net.rb +73 -77
  30. data/lib/y_petri/place.rb +8 -3
  31. data/lib/y_petri/simulation/dependency.rb +107 -0
  32. data/lib/y_petri/simulation/element_representation.rb +20 -0
  33. data/lib/y_petri/simulation/elements/access.rb +57 -0
  34. data/lib/y_petri/simulation/elements.rb +45 -0
  35. data/lib/y_petri/simulation/feature_set.rb +21 -0
  36. data/lib/y_petri/simulation/initial_marking/access.rb +55 -0
  37. data/lib/y_petri/simulation/initial_marking.rb +15 -0
  38. data/lib/y_petri/simulation/marking_clamps/access.rb +34 -0
  39. data/lib/y_petri/simulation/marking_clamps.rb +18 -0
  40. data/lib/y_petri/simulation/marking_vector/access.rb +106 -0
  41. data/lib/y_petri/simulation/marking_vector.rb +156 -0
  42. data/lib/y_petri/simulation/matrix.rb +64 -0
  43. data/lib/y_petri/simulation/place_mapping.rb +62 -0
  44. data/lib/y_petri/simulation/place_representation.rb +74 -0
  45. data/lib/y_petri/simulation/places/access.rb +121 -0
  46. data/lib/y_petri/simulation/places/clamped.rb +8 -0
  47. data/lib/y_petri/simulation/places/free.rb +8 -0
  48. data/lib/y_petri/simulation/places/types.rb +25 -0
  49. data/lib/y_petri/simulation/places.rb +41 -0
  50. data/lib/y_petri/simulation/recorder.rb +54 -0
  51. data/lib/y_petri/simulation/timed/recorder.rb +53 -0
  52. data/lib/y_petri/simulation/timed.rb +161 -261
  53. data/lib/y_petri/simulation/timeless/recorder.rb +25 -0
  54. data/lib/y_petri/simulation/timeless.rb +35 -0
  55. data/lib/y_petri/simulation/transition_representation/A.rb +58 -0
  56. data/lib/y_petri/simulation/transition_representation/S.rb +45 -0
  57. data/lib/y_petri/simulation/transition_representation/T.rb +80 -0
  58. data/lib/y_petri/simulation/transition_representation/TS.rb +46 -0
  59. data/lib/y_petri/simulation/transition_representation/Ts.rb +32 -0
  60. data/lib/y_petri/simulation/transition_representation/a.rb +30 -0
  61. data/lib/y_petri/simulation/transition_representation/s.rb +29 -0
  62. data/lib/y_petri/simulation/transition_representation/t.rb +37 -0
  63. data/lib/y_petri/simulation/transition_representation/tS.rb +38 -0
  64. data/lib/y_petri/simulation/transition_representation/ts.rb +32 -0
  65. data/lib/y_petri/simulation/transition_representation/types.rb +62 -0
  66. data/lib/y_petri/simulation/transition_representation.rb +79 -0
  67. data/lib/y_petri/simulation/transitions/A.rb +40 -0
  68. data/lib/y_petri/simulation/transitions/S.rb +24 -0
  69. data/lib/y_petri/simulation/transitions/T.rb +34 -0
  70. data/lib/y_petri/simulation/transitions/TS.rb +57 -0
  71. data/lib/y_petri/simulation/transitions/Ts.rb +60 -0
  72. data/lib/y_petri/simulation/transitions/a.rb +8 -0
  73. data/lib/y_petri/simulation/transitions/access.rb +186 -0
  74. data/lib/y_petri/simulation/transitions/s.rb +9 -0
  75. data/lib/y_petri/simulation/transitions/t.rb +22 -0
  76. data/lib/y_petri/simulation/transitions/tS.rb +55 -0
  77. data/lib/y_petri/simulation/transitions/ts.rb +58 -0
  78. data/lib/y_petri/simulation/transitions/types.rb +98 -0
  79. data/lib/y_petri/simulation/transitions.rb +21 -0
  80. data/lib/y_petri/simulation.rb +176 -781
  81. data/lib/y_petri/transition/assignment.rb +7 -5
  82. data/lib/y_petri/transition/construction.rb +119 -187
  83. data/lib/y_petri/transition/init.rb +311 -0
  84. data/lib/y_petri/transition/ordinary_timeless.rb +8 -6
  85. data/lib/y_petri/transition/timed.rb +11 -18
  86. data/lib/y_petri/transition.rb +104 -132
  87. data/lib/y_petri/version.rb +1 -1
  88. data/lib/y_petri/world/dependency.rb +40 -0
  89. data/lib/y_petri/world/petri_net_related.rb +61 -0
  90. data/lib/y_petri/{workspace/simulation_related_methods.rb → world/simulation_related.rb} +42 -49
  91. data/lib/y_petri/world.rb +27 -0
  92. data/lib/y_petri.rb +47 -99
  93. data/test/{manipulator_test.rb → agent_test.rb} +19 -17
  94. data/{lib/y_petri → test/examples}/demonstrator.rb +0 -0
  95. data/{lib/y_petri → test/examples}/demonstrator_2.rb +1 -0
  96. data/{lib/y_petri → test/examples}/demonstrator_3.rb +0 -0
  97. data/{lib/y_petri → test/examples}/demonstrator_4.rb +0 -0
  98. data/test/examples/example_2.rb +16 -0
  99. data/test/{manual_examples.rb → examples/manual_examples.rb} +0 -0
  100. data/test/net_test.rb +126 -121
  101. data/test/place_test.rb +1 -1
  102. data/test/sim_test +565 -0
  103. data/test/simulation_test.rb +338 -264
  104. data/test/transition_test.rb +77 -174
  105. data/test/world_mock.rb +12 -0
  106. data/test/{workspace_test.rb → world_test.rb} +19 -20
  107. data/test/y_petri_test.rb +4 -5
  108. metadata +101 -26
  109. data/lib/y_petri/dependency_injection.rb +0 -45
  110. data/lib/y_petri/manipulator/petri_net_related_methods.rb +0 -74
  111. data/lib/y_petri/manipulator.rb +0 -20
  112. data/lib/y_petri/net/selections.rb +0 -209
  113. data/lib/y_petri/simulation/collections.rb +0 -460
  114. data/lib/y_petri/workspace/parametrized_subclassing.rb +0 -22
  115. data/lib/y_petri/workspace/petri_net_related_methods.rb +0 -88
  116. data/lib/y_petri/workspace.rb +0 -16
  117. data/test/timed_simulation_test.rb +0 -153
@@ -19,12 +19,14 @@ module YPetri::Transition::Assignment
19
19
  # Assigns the action closure result to the codomain, regardless of cocking.
20
20
  #
21
21
  def fire!
22
- try "to call #fire! method" do
22
+ consciously "to #fire!" do
23
23
  act = note "action", is: Array( action )
24
- codomain.each_with_index do |codomain_place, i|
25
- note "assigning action element no. #{i} to place #{codomain_place}"
26
- codomain_place.marking = note "marking to assign", is: act.fetch( i )
27
- end
24
+ msg = "Wrong output arity of the action closure of #{self}"
25
+ fail TypeError, msg if act.size != codomain.size
26
+ codomain.each_with_index { |p, i|
27
+ note "assigning action element no. #{i} to #{p}"
28
+ p.marking = note "marking to assign", is: act.fetch( i )
29
+ }
28
30
  end
29
31
  return nil
30
32
  end
@@ -14,7 +14,29 @@ class YPetri::Transition
14
14
  # best explained by examples -- let us have 3 places A, B, C, for whe we will
15
15
  # create different kinds of transitions:
16
16
  #
17
+ #
18
+ # ==== TS (timed stoichiometric)
19
+ #
20
+ # Rate closure and stoichiometry has to be supplied. Rate closure arity should
21
+ # correspond to the domain size. Return arity should be 1 (to be multiplied by
22
+ # the stoichiometry vector, as in all other stoichiometric transitions).
23
+ #
24
+ # Transition.new stoichiometry: { A: -1, B: 1 },
25
+ # rate: -> a { a * 0.5 }
26
+ #
27
+ #
28
+ # ==== Ts (timed nonstoichiometric)
29
+ #
30
+ # Rate closure has to be supplied, whose arity should match the domain, and
31
+ # output arity codomain.
32
+ #
33
+ # ==== tS (timeless stoichiometric)
34
+ #
35
+ # Stoichiometry has to be supplied, action closure is optional. If supplied,
36
+ # its return arity should be 1 (to be multiplied by the stoichiometry vector).
37
+ #
17
38
  # ==== ts transitions (timeless nonstoichiometric)
39
+ #
18
40
  # Action closure is expected with return arity equal to the codomain size:
19
41
  #
20
42
  # Transition.new upstream_arcs: [A, C], downstream_arcs: [A, B],
@@ -23,43 +45,8 @@ class YPetri::Transition
23
45
  # else [1, 0] end
24
46
  # }
25
47
  #
26
- # (If C is positive, half of A's marking is moved to B, otherwise A is
27
- # incremented by 1.)
28
- #
29
- # ==== tS transitions (timeless stoichiometric)
30
- # Stochiometry has to be supplied, action closure is optional. If supplied,
31
- # its return arity should be 1 (to be multiplied by the stochiometry vector).
32
- #
33
- # If no action closure is given, a _functionless_ transition will be
34
- # constructed, with action closure == 1 * stoichiometry vector.
35
- #
36
- # ==== Tsr transitions (timed rateless nonstoichiometric)
37
- # Action closure has to be supplied, whose first argument is Δt, and the
38
- # remaining ones correspond to the domain size. Return arity of this closure
39
- # should, in turn, correspond to the codomain size.
40
- #
41
- # ==== TSr transitions (timed rateless stoichiometric)
42
- # Action closure has to be supplied, whose first argument is Δt, and the
43
- # remaining ones correspond to the domain size. Return arity of this closure
44
- # should be 1 (to be multiplied by the stoichiometry vector).
45
- #
46
- # ==== sR transitions (nonstoichiometric transitions with rate)
47
- # Rate closure has to be supplied, whose arity should correspond to the domain
48
- # size (Δt argument is not needed). Return arity of this should, in turn,
49
- # correspond to the codomain size -- it represents this transition's
50
- # contribution to the rate of change of marking of the codomain places.
51
- #
52
- # ==== SR transitions (stoichiometric transitions with rate)
53
- #
54
- # Rate closure and stoichiometry has to be supplied. Rate closure arity should
55
- # correspond to the domain size. Return arity should be 1 (to be multiplied by
56
- # the stoichiometry vector, as in all other stoichiometric transitions).
57
- #
58
- # Transition.new stoichiometry: { A: -1, B: 1 },
59
- # rate: -> a { a * 0.5 }
60
- #
61
- def initialize *args
62
- check_in_arguments *args # the big work of checking in args
48
+ def initialize *args, &block
49
+ check_in_arguments *args, &block # the big job
63
50
  extend timed? ? Timed : assignment? ? Assignment : OrdinaryTimeless
64
51
  inform_upstream_places # that they have been connected
65
52
  inform_downstream_places # that they have been connected
@@ -73,52 +60,55 @@ class YPetri::Transition
73
60
  # else then defining the duck type of the input argument collection.
74
61
  # TypeError is therefore raised if invalid collection has been supplied.
75
62
  #
76
- def check_in_arguments *aa, **oo, &block
77
- oo.may_have :stoichiometry, syn!: [ :stoichio, :s ]
78
- oo.may_have :codomain, syn!: [ :codomain_arcs, :codomain_places,
63
+ def check_in_arguments **nn, &block
64
+ nn.update( action: block ) if block_given?
65
+ nn.may_have :domain, syn!: [ :domain_arcs, :domain_places,
66
+ :upstream, :upstream_arcs, :upstream_places ]
67
+ nn.may_have :codomain, syn!: [ :codomain_arcs, :codomain_places,
79
68
  :downstream,
80
69
  :downstream_arcs, :downstream_places,
81
70
  :action_arcs ]
82
- oo.may_have :domain, syn!: [ :domain_arcs, :domain_places,
83
- :upstream, :upstream_arcs, :upstream_places ]
84
- oo.may_have :rate, syn!: [ :rate_closure, :propensity,
71
+ nn.may_have :rate, syn!: [ :rate_closure, :propensity,
85
72
  :propensity_closure ]
86
- oo.may_have :action, syn!: :action_closure
87
- oo.may_have :timed
88
- oo.may_have :domain_guard
89
- oo.may_have :codomain_guard
73
+ nn.may_have :action, syn!: :action_closure
74
+ nn.may_have :stoichiometry, syn!: [ :stoichio, :s ]
75
+ nn.may_have :domain_guard
76
+ nn.may_have :codomain_guard
90
77
 
91
- @has_rate = oo.has? :rate # was the rate was given?
78
+ # If the rate was given, the transition is timed:
79
+ @timed = nn.has? :rate
92
80
 
93
- # is the transition stoichiometric (S) or nonstoichiometric (s)?
94
- @stoichiometric = oo.has? :stoichiometry
81
+ # If stoichiometry was given, the transition is stoichiometric:
82
+ @stoichiometric = nn.has? :stoichiometry
95
83
 
96
- # downstream description arguments: codomain, stoichiometry (if S)
84
+ # Downstream description involves the codomain, and the stochiometry
85
+ # (for stoichiometric transitions only):
97
86
  if stoichiometric? then
98
- @codomain, @stoichiometry = check_in_downstream_description_for_S( oo )
99
- else # s transitions have no stoichiometry
100
- @codomain = check_in_downstream_description_for_s( oo )
87
+ @codomain, @stoichiometry = __downstream_for_S__( **nn )
88
+ else
89
+ @codomain = __downstream_for_s__( **nn )
101
90
  end
102
91
 
103
- # check in domain first, :missing symbol may appear
104
- @domain = check_in_domain( oo )
92
+ # Check in the domain first, :missing symbol may be returned if the user
93
+ # has not supplied the domaing (the constructor will attempt to guessf it
94
+ # automatically).
95
+ @domain = __domain__( **nn )
105
96
 
106
- # upstream description arguments; also takes care of :missing domain
107
- if has_rate? then
108
- @domain, @rate_closure, @timed, @functional =
109
- check_in_upstream_description_for_R( oo, &block )
97
+ # Upstream description involves the domain and the rate/action closure.
98
+ # Also, :missing domain is taken care of here.
99
+ if timed? then
100
+ @domain, @rate_closure, @functional = __upstream_for_T__( **nn )
110
101
  else
111
- @domain, @action_closure, @timed, @functional =
112
- check_in_upstream_description_for_r( oo, &block )
102
+ @domain, @action_closure, @functional = __upstream_for_t__( **nn )
113
103
  end
114
104
 
115
- # optional assignment action:
116
- @assignment_action = check_in_assignment_action( oo )
105
+ # Optional assignment action:
106
+ @assignment_action = __assignment_action__( **nn )
107
+
108
+ # Optional type guards for domain / codomain:
109
+ @domain_guard, @codomain_guard = __guards__( **nn )
110
+ end
117
111
 
118
- # optional type guards for domain / codomain:
119
- @domain_guard, @codomain_guard = check_in_guards( oo )
120
- end # def check_in_arguments
121
-
122
112
  # Validates that the supplied collection consists only of places of
123
113
  # correct type. Second optional argument customizes the error message.
124
114
  #
@@ -134,10 +124,10 @@ class YPetri::Transition
134
124
  coll == coll.uniq
135
125
  end
136
126
  end
137
-
127
+
138
128
  # Private method, part of #initialize argument checking-in.
139
129
  #
140
- def check_in_domain( oo )
130
+ def __domain__( **oo )
141
131
  if oo.has? :domain then
142
132
  sanitize_place_collection( oo[:domain], "supplied domain" )
143
133
  else
@@ -150,131 +140,73 @@ class YPetri::Transition
150
140
  # Barring the caller's error, missing domain can mean:
151
141
  # 1. empty domain
152
142
  # 2. domain == codomain
153
- # This will be figured later by rate/action closure arity
143
+ # This will be figured later by the rate/action closure arity.
154
144
  end
155
145
  end
156
146
  end
157
147
 
158
- # Private method, part of the init process when :rate is given. Also takes
159
- # care for missing domain (@domain == :missing).
148
+ # Private method, part of the init process for timed transitions. Also takes
149
+ # care for :missing domain, if :missing.
160
150
  #
161
- def check_in_upstream_description_for_R( oo, &block )
151
+ def __upstream_for_T__( **oo )
162
152
  _domain = domain # this method may modify domain
163
- fail ArgumentError, "Rate/propensity and action may not be both given!" if
164
- oo.has? :action # check against colliding :action named argument
165
- fail ArgumentError, "If block is given, rate must not be given!" if block
166
- # Let's figure the rate closure now. (Block is never used.)
167
- rate_λ = case ra = oo[:rate]
168
- when Proc then # We received the closure directly,
169
- ra.tap do |λ| # but we've to be concerned about missing domain.
170
- if domain == :missing then # we've to figure user's intent
171
- _domain = if λ.arity == 0 then [] # user meant empty domain
172
- else codomain end # user meant domain == codomain
173
- else # domain not missing
174
- fail TypeError, "Rate closure arity (#{λ.arity}) > " +
175
- "domain (#{domain.size})!" if λ.arity.abs > domain.size
176
- end
177
- end
178
- else # We received something else, must guess user's intent.
179
- if stoichiometric? then # user's intent was mass action
180
- fail TypeError, "When a number is supplied as rate, " +
181
- "domain must not be given!" if oo.has? :domain
182
- construct_standard_mass_action( ra )
183
- else # user's intent was constant closure
184
- fail TypeError, "When rate is a number and stoichiometry " +
185
- "is not given, codomain size must be 1!" unless
186
- codomain.size == 1
187
- # Missing domain is OK here,
188
- _domain = [] if domain == :missing
189
- # but if it was supplied explicitly, it must be empty.
190
- fail TypeError, "Rate is a number, but non-empty domain " +
191
- "was supplied!" unless domain.empty? if oo.has?( :domain )
192
- -> { ra }
193
- end
194
- end
195
- # R transitions are implicitly timed
196
- _timed = true
197
- # check against colliding :timed argument
198
- oo[:timed].tE :timed, "not be false if rate given" if oo.has? :timed
199
- # R transitions are implicitly functional
200
- _functional = true
201
- return _domain, rate_λ, _timed, _functional
153
+ _functional = true # T transitions are implicitly functional
154
+ fail ArgumentError, "Rate and action collision!" if oo.has? :action
155
+ # Let's figure the rate closure now.
156
+ λ = oo[:rate]
157
+ if λ.is_a? Proc then
158
+ # Solve :missing domain:
159
+ _domain = λ.arity == 0 ? [] : codomain if domain == :missing
160
+ # Validate arity:
161
+ msg = "Rate closure arity (#{λ.arity}) > domain (#{domain.size})!"
162
+ fail TypeError, msg if λ.arity.abs > domain.size
163
+ else # not a Proc, must guess user's intent
164
+ λ = if stoichiometric? then # standard mass action
165
+ msg = "With numeric rate, domain must not be given!"
166
+ fail TypeError, msg if oo.has? :domain
167
+ __standard_mass_action__( λ )
168
+ else # constant closure
169
+ msg = "With numeric rate and no stoichio., codomain size must be 1!"
170
+ fail TypeError, msg unless codomain.size == 1
171
+ _domain = [] if domain == :missing # Missing domain is OK here,
172
+ # But in case it was supplied explicitly, it must be empty.
173
+ msg = "Rate is a number, but domain is non-empty!"
174
+ fail TypeError, msg unless domain.empty? if oo.has? :domain
175
+ -> { λ } # the closure itself
176
+ end
177
+ end
178
+ return _domain, λ, _functional
202
179
  end
203
180
 
204
181
  # Private method, part of the init process when :rate is not given. Also
205
182
  # takes care for missing domain (@domain == :missing).
206
183
  #
207
- def check_in_upstream_description_for_r( oo, &block )
208
- _domain = domain # this method may modify domain
184
+ def __upstream_for_t__( **oo )
185
+ _domain = domain # this method may modify domain
209
186
  _functional = true
210
- # Was action closure was given explicitly?
187
+ # Was action given explicitly?
211
188
  if oo.has? :action then
212
- fail ArgumentError, "If block is given, rate must not be given!" if block
213
- action_λ = oo[:action].aT_is_a Proc, "supplied action named argument"
214
- if oo.has? :timed then
215
- _timed = oo[:timed]
216
- # Time to worry about the domain_missing
217
- if domain == :missing then # figure user's intent from closure arity
218
- _domain = if action_λ.arity == ( _timed ? 1 : 0 ) then
219
- [] # user meant empty domain
220
- else
221
- codomain # user meant domain same as codomain
222
- end
223
- else # domain not missing
224
- fail TypeError, "Rate closure arity (#{rate_arg.arity}) > domain " +
225
- "size (#{domain.size})!" if action_λ.arity.abs > domain.size
226
- end
227
- else # :timed argument not supplied
228
- if domain == :missing then
229
- # If no domain was supplied, there is no way to reasonably figure
230
- # out the user's intent, except when arity is 0:
231
- _domain = case action_λ.arity
232
- when 0 then
233
- _timed = false
234
- [] # empty domain is implied
235
- else # no deduction of user intent possible
236
- fail ArgumentError, "Too much ambiguity: Rateless " +
237
- "transition with neither domain nor timedness given."
238
- end
239
- else # domain not missing
240
- # Even if the user did not bother to inform us explicitly about
241
- # timedness, we can use closure arity as a clue. If it equals the
242
- # domain size, leaving no room for Δtime argument, the user intent
243
- # was to create timeless transition. If it equals domain size + 1,
244
- # theu user intended to create a timed transition.
245
- _timed = case action_λ.arity
246
- when domain.size then false
247
- when domain.size + 1 then true
248
- else # no deduction of user intent possible
249
- fail ArgumentError, "Timedness was not specified, and " +
250
- "action closure arity (#{action_λ.arity}) does not " +
251
- "give a clear hint on it!"
252
- end
253
- end
189
+ λ = oo[:action].aT_is_a Proc, "supplied action named argument"
190
+ # Time to worry about the domain_missing, guess the user's intention:
191
+ if domain == :missing then
192
+ _domain = ( λ.arity == 0 ? [] : codomain )
193
+ else
194
+ msg = "Action closure arity (#{λ.arity}) > domain size (#{domain.size})!"
195
+ fail TypeError, msg if λ.arity.abs > domain.size
254
196
  end
255
- else # rateless cases with no action closure specified
256
- # Consume block, if given:
257
- check_in_upstream_for_r oo.update( action: block ) if block
258
- # If there is really really no closure, an assumption must be made taken
259
- # as for the transition's action, in particular, -> { 1 } closure:
260
- action_λ = -> { 1 }
261
- # The transition is then required to be stoichiometric and timeless.
262
- # Domain will be required empty.
263
- fail ArgumentError, "Stoichiometry is compulsory, if no rate/action " +
264
- "was supplied." unless stoichiometric?
265
- # With this, we can drop worries about missing domain.
266
- fail ArgumentError, "When no rate/propensity or action is supplied, " +
267
- "the transition cannot be timed." if oo[:timed] if oo.has? :timed
268
- _timed = false
269
- _domain = []
270
- _functional = false # the transition is considered functionless
197
+ else # functionless transition
198
+ _functional = false
199
+ λ = -> { 1 }
200
+ msg = "Stoichiometry is compulsory, if no rate/action was supplied."
201
+ fail ArgumentError, msg unless S?
202
+ _domain = [] # in any case, the domain is empty
271
203
  end
272
- return _domain, action_λ, _timed, _functional
204
+ return _domain, λ, _functional
273
205
  end
274
206
 
275
207
  # Default rate closure for SR transitions whose rate is hinted as a number.
276
208
  #
277
- def construct_standard_mass_action( num )
209
+ def __standard_mass_action__( num )
278
210
  # assume standard mass-action law
279
211
  nonpositive_coeffs = stoichiometry.select { |coeff| coeff <= 0 }
280
212
  # the closure takes markings of the domain as its arguments
@@ -294,21 +226,21 @@ class YPetri::Transition
294
226
  # Private method, checking in downstream specification from the argument
295
227
  # field for stoichiometric transition.
296
228
  #
297
- def check_in_downstream_description_for_S( oo )
229
+ def __downstream_for_S__( **oo )
298
230
  codomain, stoichio =
299
231
  case oo[:stoichiometry]
300
232
  when Hash then
301
233
  # contains pairs { codomain place => stoichiometry coefficient }
302
- fail ArgumentError, "With hash-type stoichiometry, :codomain " +
303
- "argument must not be given!" if oo.has? :codomain
234
+ msg = "With hash-type stoichiometry, :codomain must not be given!"
235
+ fail ArgumentError, msg if oo.has? :codomain
304
236
  oo[:stoichiometry].each_with_object [[], []] do |(cd_pl, coeff), memo|
305
- memo[0] << cd_pl
306
- memo[1] << coeff
307
- end
237
+ memo[0] << cd_pl
238
+ memo[1] << coeff
239
+ end
308
240
  else
309
241
  # array of stoichiometry coefficients
310
- fail ArgumentError, "With array-type stoichiometry, :codomain " +
311
- "argument must be given!" unless oo.has? :codomain
242
+ msg = "With array-type stoichiometry, :codomain must be given!"
243
+ fail ArgumentError unless oo.has? :codomain
312
244
  [ oo[:codomain], Array( oo[:stoichiometry] ) ]
313
245
  end
314
246
  # enforce that stoichiometry is a collection of numbers
@@ -319,7 +251,7 @@ class YPetri::Transition
319
251
  # Private method, checking in downstream specification from the argument
320
252
  # field for nonstoichiometric transition.
321
253
  #
322
- def check_in_downstream_description_for_s( oo )
254
+ def __downstream_for_s__( **oo )
323
255
  # codomain must be explicitly given - no way around it:
324
256
  fail ArgumentError, "For non-stoichiometric transitions, :codomain " +
325
257
  "argument is compulsory." unless oo.has? :codomain
@@ -328,7 +260,7 @@ class YPetri::Transition
328
260
 
329
261
  # Private method, part of #initialize argument checking-in.
330
262
  #
331
- def check_in_assignment_action( oo )
263
+ def __assignment_action__( **oo )
332
264
  if oo.has? :assignment_action, syn!: [ :assignment, :assign, :A ] then
333
265
  if timed? then
334
266
  false.tap do
@@ -341,7 +273,7 @@ class YPetri::Transition
341
273
 
342
274
  # Private method, part of #initialize argument checking-in
343
275
  #
344
- def check_in_guards( oo )
276
+ def __guards__( **oo )
345
277
  if oo.has? :domain_guard then
346
278
  oo[:domain_guard].aT_is_a Proc, "supplied domain guard"
347
279
  else