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
@@ -1,9 +1,8 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
2
 
3
- require_relative 'dependency_injection'
4
3
  require_relative 'transition/arcs'
5
4
  require_relative 'transition/cocking'
6
- require_relative 'transition/construction'
5
+ require_relative 'transition/init'
7
6
  require_relative 'transition/timed'
8
7
  require_relative 'transition/ordinary_timeless'
9
8
  require_relative 'transition/assignment'
@@ -14,123 +13,106 @@ require_relative 'transition/assignment'
14
13
  # === Domain and codomin
15
14
  #
16
15
  # Each transition has a _domain_ (upstream places) and _codomain_ (downstream
17
- # places). Upstream places are those, whose marking directly affects
18
- # the transition. Downstream places are those, whose marking is directly affected
19
- # by the transition.
16
+ # places). Upstream places are those, whose marking affects the transition.
17
+ # Downstream places are those affected by the transition.
20
18
  #
21
19
  # === Action and action vector
22
20
  #
23
- # Every transition has an _action_ -- the operation it represents. The action
24
- # of _non-stoichiometric_ transitions is directly specified by the _action_
21
+ # Every transition _action_ -- the operation it represents. The action of
22
+ # _non-stoichiometric_ transitions is directly specified by its _action_
25
23
  # _closure_ (whose output arity should match the codomain size.) For
26
- # _stoichiometric_ transitions, the result of the action closure has to be
27
- # multiplied by the transition's _stoichiometry_ _vector_ to obtain the action.
28
- # Action of the _transitions_ _with_ _rate_ is specified indirectly by the
29
- # _rate_ _closure_.
24
+ # _stoichiometric_ transitions, the action closure result must be multiplied
25
+ # by the transition's _stoichiometry_ _vector_. _Timed_ _transitions_ have
26
+ # _rate_ _closure_. Their action can be obtained by multiplying their rate
27
+ # by Δtime.
30
28
  #
31
29
  # === Rate
32
30
  #
33
- # In YPetri domain model, marking is always a discrete number of _tokens_ -- as
34
- # Carl Adam Petri handed it down to us. YPetri recognizes the usefulness of
35
- # representing a large number of tokens by a floating point number, but sees it
36
- # as a pragmatic measure only. Other Petri net implementations often make class
37
- # distincion between discrete and continuous places, and also distinguish between
38
- # _flux_ ("flow" of the continous transitions) and _propensity_ (firing
39
- # probability of discrete transitions). In YPetri, flux and propensity are
40
- # unified under the term _rate_, and the choice between discrete and stochastic
41
- # computation is seen as a concern of the simulation, not of the model.
31
+ # In YPetri, marking is always considered a discrete number of _tokens_ (as
32
+ # C. A. Petri has handed it down to us). Usefulness of floating point numbers
33
+ # in representing larger amounts of tokens is acknowledged, but seen as a
34
+ # pragmatic measure, an implementation detail. There is no class distinction
35
+ # between discrete vs. continuous places / transitions. Often we see continuous
36
+ # transitions with their _flux_ (flow rate) ditinguished from discrete
37
+ # stochastic transitions with their _propensity_ (likelihood of firing in a
38
+ # time unit). In YPetri, flux and propensity are unified under a single term
39
+ # _rate_, and the choice between discrete and stochastic computation is a
40
+ # concern of the simulation, not of the object model.
42
41
  #
43
42
  # === Basic transition types
44
43
  #
45
- # There are 6 basic types of transitions in YPetri:
44
+ # There are 4 basic transition types in YPetri:
46
45
  #
47
- # * *ts* – timeless nonstoichiometric
46
+ # * *TS* – timed stoichiometric
48
47
  # * *tS* – timeless stoichiometric
49
- # * *Tsr* – timed rateless nonstoichiometric
50
- # * *TSr* – timed rateless stoichiometric
51
- # * *sR* – nonstoichiometric with rate
52
- # * *SR* – stoichiometric with rate
48
+ # * *Ts* – timed nonstoichiometric
49
+ # * *ts* – timeless nonstoichiometric
53
50
  #
54
- # They arise by combining the 3 basic qualities:
51
+ # They arise by combining 2 qualities:
55
52
  #
56
- # 1. *Stoichiometricity*: _stoichiometric_ (*S*) / _nonstoichiometric_ (*s*)
57
- # 2. *Timedness*: _timed_ (*T*) / _timeless_ (*t*)
58
- # 3. *Having* *rate*: having _rate_ (*R*) / not having rate (_rateless_) (*r*)
53
+ # 1. *Timedness*: _timed_ (*T*) / _timeless_ (*t*)
54
+ # 2. *Stoichiometricity*: _stoichiometric_ (*S*) / _nonstoichiometric_ (*s*)
59
55
  #
60
- # ==== 1. Stoichiometricity
56
+ # ==== Timedness
61
57
  #
62
- # * For *stoichiometric* transitions:
63
- # - _either_ <b>rate vector</b> is obtained as
64
- # <b>rate * stoichiometry vector</b>,
65
- # - _or_ <b>action vector</b> is obtained as
66
- # <b>action * stoichiometry vector</b>
67
- # * For *non-stoichiometric* transitions:
68
- # - _either_ <b>rate vector</b> is obtained as the <b>rate closure result</b>,
69
- # - _or_ <b>action vector</b> is obtained as the <b>action closure result</b>.
58
+ # * Timed transitions have _rate_ _closure_, whose result is to be multiplied
59
+ # by +Δtime+.
60
+ # * Timeless transitions have _action_ _closure_, whose result does not need
61
+ # to be multiplied by time.
62
+ #
63
+ # Summary: Having vs. not having rate distinguishes the <em>need to multiply the
64
+ # closure result by Δ time</em>.
70
65
  #
71
- # Summary: stoichiometricity distinguishes the <b>need to multiply the
72
- # rate/action closure result by stoichiometry</b>.
66
+ # ==== Stoichiometricity
73
67
  #
74
- # ==== 2. Having rate
68
+ # * *TS* transitions -- <b>rate vector = rate * stoichiometry vector</b>
69
+ # * *tS* transitions -- <b>action vector = action * stoichiometry vector</b>
70
+ # * *Ts* transitions -- <b>rate vector = rate closure result</b>
71
+ # * *ts* transitions -- <b>action vector = action closure result</b>
75
72
  #
76
- # * Transitions *with* *rate* have a _rate_ _closure_, whose result is to be
77
- # multiplied by +Δt+.
78
- # * For transitions *without* *rate* (*rateless* transitions), the action
79
- # closure specifies the action *directly*.
80
- #
81
- # Summary: Having vs. not having rate distinguishes the <b>need to multiply the
82
- # closure result by Δ time</b> -- differentiability of the action by time.
83
- #
84
- # ==== 3. Timedness
73
+ # Summary: stoichiometricity distinguishes the <em>need to multiply the rate/action
74
+ # closure result by stoichiometry</em>.
85
75
  #
86
- # * Timed transitions are defined as those, whose action has time as a parameter.
87
- # - Transitions with rate are therefore always timed.
88
- # - For rateless transitions, being timed means, that their action closure
89
- # <b>expects Δt as its first argument</b> -- arity thus equals codomain
90
- # size + 1.
91
- # * Timeless transitions are those, whose action does not have time as
92
- # a parameter. Timeless transitions are necessarily also rateless.
76
+ # === Assignment action
93
77
  #
94
- # Summary: In rateless transitions, timedness distinguishes the <b>need to
95
- # supply time step duration as the first argument to the action closure</b>.
96
- # As the transitions with rate are necessarily timed, and timeless transitions
97
- # necessarily rateless, there are only 6 instead of 2 ** 3 == 8 transition types.
98
- #
99
- # === Other transition attributes
100
- #
101
- # ==== Assignment transitions (_A_ _transitions_)
102
- # If +:assignment_action+ option is set to _true_, it makes the transition
103
- # entirely replace the codomain marking with its action closure result -- just
104
- # like spreadsheet functions do. This, however, is just a convenience, and does
105
- # not constitue a novel transition type, as it can be easily emulated by an
106
- # ordinary ts transition caring to subtract the current domain marking before
107
- # adding the desired values.
78
+ # _Assignment_ _transitions_ (_*A*_ _transitions_) are special transitions, that
79
+ # _replace_ the codomain marking rather than modifying it -- they _assign_ new
80
+ # marking to their codomain, like we are used to from spreadsheets. Technically,
81
+ # this behavior is easily achievable with normal *ts* transitions, so the
82
+ # existence of separate *A* transitions is just a convenience, not a new type of
83
+ # a transition in the mathematical sense.
108
84
  #
109
85
  # ==== _Functional_ / _functionless_ transitions
110
- # Other Petri net implementation often make a distinction between "ordinary"
111
- # and "functional" transitions, where "ordinary" ("functionless") are the
112
- # transitions as Carl Adam Petri handed them down to us. YPetri transtions
113
- # are generally "functional", but the possibility of functionless transitions
114
- # is also provided -- stoichiometric transitions with no action or rate
115
- # specified become functionless transitions.
116
- # definition does not speak about transition "functions". The transitions are
117
- # defined as timeless and more or less assumed to be stoichiometric. Therefore,
118
- # in +YPetri::Transition+ constructor, stoichiometric transitions with no
119
- # function specified become functionless vanilla Petri net transitions.
86
+ #
87
+ # Other Petri net implementation often distinguies between "ordinary" (vanilla
88
+ # as per C. A. Petri) and _functional_ transitions, whose operation is governed
89
+ # by a function. In YPetri, transitions are generally _functional_, but there
90
+ # remains a possibility of creating vanilla (_functionless_) transitions by not
91
+ # specifying any rate / action, while specifying the stoichiometry. Action
92
+ # closure as per C. A. Petri is automatically constructed for these.
120
93
  #
121
94
  class YPetri::Transition
122
95
  include NameMagic
123
- include YPetri::DependencyInjection
96
+ include YPetri::World::Dependency
97
+
98
+ class << self
99
+ include YPetri::World::Dependency
100
+ end
101
+
102
+ delegate :world, to: "self.class"
124
103
 
125
104
  BASIC_TRANSITION_TYPES = {
126
- ts: "timeless nonstoichiometric transition",
127
- tS: "timeless stoichiometric transition",
128
- Tsr: "timed rateless nonstoichiometric transition",
129
- TSr: "timed rateless stoichiometric transition",
130
- sR: "nonstoichiometric transition with rate",
131
- SR: "stoichiometric transition with rate"
105
+ TS: "timed stoichiometric",
106
+ tS: "timeless stoichiometric",
107
+ Ts: "timed nonstoichiometric",
108
+ ts: "timeless nonstoichiometric"
132
109
  }
133
110
 
111
+ def TS?; type == :TS end
112
+ def Ts?; type == :Ts end
113
+ def tS?; type == :tS end
114
+ def ts?; type == :ts end
115
+
134
116
  # Domain, or 'upstream arcs', is a collection of places, whose marking
135
117
  # directly affects the transition's action.
136
118
  #
@@ -155,13 +137,14 @@ class YPetri::Transition
155
137
  # Is the transition stoichiometric?
156
138
  #
157
139
  def stoichiometric?; @stoichiometric end
158
- alias :s? :stoichiometric?
140
+ alias :S? :stoichiometric?
159
141
 
160
142
  # Is the transition nonstoichiometric? (Opposite of #stoichiometric?)
161
143
  #
162
144
  def nonstoichiometric?
163
145
  not stoichiometric?
164
146
  end
147
+ alias :s? :nonstoichiometric?
165
148
 
166
149
  # Stoichiometry (implies that the transition is stoichiometric).
167
150
  #
@@ -181,18 +164,6 @@ class YPetri::Transition
181
164
  stoichio.with_keys { |k| k.name || k.object_id }
182
165
  end
183
166
 
184
- # Does the transition have rate?
185
- #
186
- def has_rate?
187
- @has_rate
188
- end
189
-
190
- # Is the transition rateless?
191
- #
192
- def rateless?
193
- not has_rate?
194
- end
195
-
196
167
  # In YPetri, _rate_ is a unifying term for both _flux_ and _propensity_,
197
168
  # both of which are treated as aliases of _rate_. The decision between
198
169
  # discrete and continuous computation is a concern of the simulation.
@@ -217,12 +188,14 @@ class YPetri::Transition
217
188
  def timed?
218
189
  @timed
219
190
  end
191
+ alias T? timed?
220
192
 
221
193
  # Is the transition timeless? (Opposite of #timed?)
222
194
  #
223
195
  def timeless?
224
196
  not timed?
225
197
  end
198
+ alias t? timeless?
226
199
 
227
200
  # Is the transition functional?
228
201
  # Explanation: If rate or action closure is supplied, a transition is always
@@ -241,43 +214,34 @@ class YPetri::Transition
241
214
  not functional?
242
215
  end
243
216
 
244
- # Reports the transition's membership in one of 6 basic types :
245
- # 1. ts ..... timeless nonstoichiometric
246
- # 2. tS ..... timeless stoichiometric
247
- # 3. Tsr .... timed rateless nonstoichiometric
248
- # 4. TSr .... timed rateless stoichiometric
249
- # 5. sR ..... nonstoichiometric with rate
250
- # 6. SR ..... stoichiometric with rate
217
+ # Reports the transition's membership in one of the 4 basic types:
251
218
  #
252
- def basic_type
253
- if has_rate? then stoichiometric? ? :SR : :sR
254
- elsif timed? then stoichiometric? ? :TSr : :Tsr
255
- else stoichiometric? ? :tS : :ts end
256
- end
257
-
258
- # Reports transition's type (basic type + whether it's an assignment
259
- # transition).
219
+ # 1. TS .... timed stoichiometric
220
+ # 2. tS .... timeless stoichiometric
221
+ # 3. Ts .... timed nonstoichiometric
222
+ # 4. ts .... timeless nonstoichiometric
223
+ #
224
+ # plus the fifth type
225
+ #
226
+ # 5. A .... assignment transitions
260
227
  #
261
228
  def type
262
- assignment_action? ? "A(ts)" : basic_type
229
+ return :A if assignment_action?
230
+ timed? ? ( stoichiometric? ? :TS : :Ts ) : ( stoichiometric? ? :tS : :ts )
263
231
  end
264
232
 
265
- # Is it an assignment transition?
266
- #
267
- # A transition can be specified to have 'assignment action', in which case
268
- # it completely replaces codomain marking with the objects resulting from
269
- # the transition's action. Note that for numeric marking, specifying
270
- # assignment action is a matter of convenience, not necessity, as it can
271
- # be emulated by fully subtracting the present codomain values and adding
272
- # the numbers computed by the transition to them. Assignment action flag
273
- # is a matter of necessity only when codomain marking involves objects
274
- # not supporting subtraction/addition (which is out of the scope of Petri's
275
- # original specification anyway.)
233
+ # Is it an assignment transition? (Transitions with 'assignment action'
234
+ # completely replace their codomain's marking.)
276
235
  #
277
236
  def assignment_action?; @assignment_action end
278
237
  alias :assignment? :assignment_action?
238
+ alias :A? :assignment_action?
279
239
 
280
- # Zero action
240
+ # Is it a non-assignment transition? (Opposite of +#A?+)
241
+ #
242
+ def a?; ! assignment_action? end
243
+
244
+ # Zero action.
281
245
  #
282
246
  def zero_action
283
247
  codomain.map { 0 }
@@ -325,8 +289,16 @@ class YPetri::Transition
325
289
  #
326
290
  def to_s
327
291
  "#<Transition: %s>" %
328
- "#{name.nil? ? '' : '%s ' % name }(#{basic_type}%s)%s" %
292
+ "#{name.nil? ? '' : '%s ' % name }(#{type}%s)%s" %
329
293
  [ "#{assignment_action? ? ' Assign.' : ''}",
330
294
  "#{name.nil? ? ' id:%s' % object_id : ''}" ]
331
295
  end
296
+
297
+ def place id
298
+ super rescue Place().instance( id )
299
+ end
300
+
301
+ def transition id
302
+ super rescue Transition().instance( id )
303
+ end
332
304
  end # class YPetri::Transition
@@ -1,4 +1,4 @@
1
1
  module YPetri
2
- VERSION = "2.0.15"
2
+ VERSION = "2.1.3"
3
3
  DEBUG = false
4
4
  end
@@ -0,0 +1,40 @@
1
+ #encoding: utf-8
2
+
3
+ # Provides basic skeleton for dependency injection for the triples of the
4
+ # parametrized subclasses of Place, Transition and Net in different workspaces.
5
+ #
6
+ module YPetri::World::Dependency
7
+ delegate :Place, :Transition, :Net, to: :world
8
+
9
+ # Place instance identification.
10
+ #
11
+ def place id
12
+ world.place( id )
13
+ end
14
+
15
+ # Transition instance identification.
16
+ #
17
+ def transition id
18
+ world.transition( id )
19
+ end
20
+
21
+ # Element instance identification.
22
+ #
23
+ def element id
24
+ begin
25
+ place( id )
26
+ rescue NameError, TypeError
27
+ begin
28
+ transition( id )
29
+ rescue NameError, TypeError => err
30
+ raise TypeError, "Unrecognized place or transition: #{element} (#{err})"
31
+ end
32
+ end
33
+ end
34
+
35
+ # Net instance identification.
36
+ #
37
+ def net id
38
+ Net().instance( id )
39
+ end
40
+ end # module YPetri::DependencyInjection
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ # Workspace instance methods related to Petri net itsef (places, transitions,
4
+ # net instances).
5
+ #
6
+ module YPetri::World::PetriNetRelated
7
+ # Instance initialization.
8
+ #
9
+ def initialize
10
+ set_up_Top_net # Sets up :Top net encompassing all places and transitions.
11
+ super
12
+ end
13
+
14
+ # Returns a place instance identified by the argument.
15
+ #
16
+ def place id
17
+ Place().instance( id )
18
+ end
19
+
20
+ # Returns a transition instance identified by the argument.
21
+ #
22
+ def transition id
23
+ Transition().instance( id )
24
+ end
25
+
26
+ # Returns a net instance identified by the argument.
27
+ #
28
+ def net id
29
+ Net().instance( id )
30
+ end
31
+
32
+ # Place instances.
33
+ #
34
+ def places
35
+ Place().instances
36
+ end
37
+
38
+ # Transition instances.
39
+ #
40
+ def transitions
41
+ Transition().instances
42
+ end
43
+
44
+ # Net instances.
45
+ #
46
+ def nets
47
+ Net().instances
48
+ end
49
+
50
+ private
51
+
52
+ # Creates all-encompassing Net instance named :Top.
53
+ #
54
+ def set_up_Top_net
55
+ Net().new name: :Top # all-encompassing :Top net
56
+ # Hook new places to add themselves magically to the :Top net.
57
+ Place().new_instance_closure { |new_inst| net( :Top ) << new_inst }
58
+ # Hook new transitions to add themselves magically to the :Top net.
59
+ Transition().new_instance_closure { |new_inst| net( :Top ) << new_inst }
60
+ end
61
+ end # module YPetri::World::PetriNetRelated
@@ -1,9 +1,10 @@
1
- # -*- coding: utf-8 -*-
2
- # Workspace instance methods related to simulation (initial marking
3
- # collections, clamp collections, inital marking collections, management
4
- # of simulations...)
1
+ # encoding: utf-8
2
+
3
+ # Instance methods of the World class related to simulation (initial marking
4
+ # collections, clamp collections, inital marking collections, management of
5
+ # simulations...)
5
6
  #
6
- module YPetri::Workspace::SimulationRelatedMethods
7
+ module YPetri::World::SimulationRelated
7
8
  # Collections of clamps, initial marking vectors, and simulation settings.
8
9
  #
9
10
  attr_reader :clamp_collections,
@@ -17,30 +18,37 @@ module YPetri::Workspace::SimulationRelatedMethods
17
18
  @clamp_collections = { Base: {} } # { collection name => clamp hash }
18
19
  @initial_marking_collections = { Base: {} } # { collection name => im hash }
19
20
  @simulation_settings_collections = # { collection name => ss hash }
20
- { Base: YPetri::DEFAULT_SIMULATION_SETTINGS.call }
21
+ { Base: ( YPetri::Simulation::DEFAULT_SETTINGS.call
22
+ .update YPetri::Simulation::Timed::DEFAULT_SETTINGS.call ) }
21
23
  super
22
24
  end
23
25
 
24
26
  # Hash of simulation instances and their settings.
25
27
  #
26
- def simulations; @simulations end
28
+ def simulations
29
+ @simulations
30
+ end
27
31
 
28
32
  # Clamp collection names.
29
33
  #
30
- def clamp_collection_names; @clamp_collections.keys end
31
- alias cc_names clamp_collection_names
34
+ def clamp_collection_names
35
+ @clamp_collections.keys
36
+ end
37
+ alias ncc clamp_collection_names
32
38
 
33
39
  # Initial marking collection names.
34
40
  #
35
- def initial_marking_collection_names; @initial_marking_collections.keys end
36
- alias imc_names initial_marking_collection_names
41
+ def initial_marking_collection_names
42
+ @initial_marking_collections.keys
43
+ end
44
+ alias nimc initial_marking_collection_names
37
45
 
38
46
  # Simulation settings collection names.
39
47
  #
40
48
  def simulation_settings_collection_names
41
49
  @simulation_settings_collections.keys
42
50
  end
43
- alias ssc_names simulation_settings_collection_names
51
+ alias nssc simulation_settings_collection_names
44
52
 
45
53
  # Clamp collection identified by the argument.
46
54
  #
@@ -137,47 +145,32 @@ module YPetri::Workspace::SimulationRelatedMethods
137
145
  #
138
146
  # * default_ss = { step_size: 0.1, sampling_period: 5, target_time: 60 }
139
147
  #
140
- def new_timed_simulation( net: Net()::Top, **nn )
141
- net_ɪ = net( net )
148
+ def new_simulation( net: Net()::Top, **nn )
149
+ net_inst = net( net )
142
150
  nn.may_have :cc, syn!: :clamp_collection
143
151
  nn.may_have :imc, syn!: :initial_marking_collection
144
152
  nn.may_have :ssc, syn!: :simulation_settings_collection
145
153
  cc_id = nn.delete( :cc ) || :Base
146
154
  imc_id = nn.delete( :imc ) || :Base
147
155
  ssc_id = nn.delete( :ssc ) || :Base
148
-
149
- # simulation key
150
- key = nn.may_have( :ɴ, syn!: :name ) || # either explicit
151
- { net: net_ɪ, cc: cc_id, imc: imc_id, ssc: ssc_id }.merge( nn ) # or constructed
152
-
156
+ # Construct the simulation key:
157
+ key = if nn.has? :name, syn!: :ɴ then # explicit key (name)
158
+ nn[:name]
159
+ else # constructed key
160
+ {}.merge( net: net_inst,
161
+ cc: cc_id,
162
+ imc: imc_id,
163
+ ssc: ssc_id )
164
+ .merge( nn )
165
+ end
153
166
  # Let's clarify what we got so far.
154
- simulation_settings = self.ssc( ssc_id )
155
- clamp_hash = self.cc( cc_id )
156
- im_hash = self.imc( imc_id )
157
-
158
- # Use places' :default_marking in absence of explicit initial marking.
159
- untreated = net_ɪ.places.select do |p|
160
- ! clamp_hash.map { |k, _| place k }.include? p and
161
- ! im_hash.map { |k, _| place k }.include? p
162
- end
163
- im_complement = Hash[ untreated.zip( untreated.map &:default_marking ) ]
164
-
165
- # If marking can't be figured, raise nice errors.
166
- missing = im_complement.select { |_, v| v.nil? }
167
- err = lambda { |array, txt=''|
168
- raise TypeError, "Missing clamp and/or initial marking for %s#{txt}!" %
169
- Array( array ).map { |i| missing.keys[i] }.join( ', ' )
170
- }
171
- case missing.size
172
- when 0 then im_hash = im_hash.merge im_complement # everything's OK
173
- when 1 then err.( 0 )
174
- when 2 then err.( [0, 1] )
175
- when 3 then err.( [0, 1, 2] )
176
- else err.( [0, 1], " and #{missing.size-2} more places" ) end
177
-
178
- # Finally, create and return the simulation
179
- named_args = simulation_settings.merge( initial_marking: im_hash,
180
- marking_clamps: clamp_hash ).merge( nn )
181
- @simulations[ key ] = net_ɪ.new_timed_simulation **named_args
182
- end # def new_timed_simulation
183
- end # module YPetri::Workspace::SimulationRelatedMethods
167
+ sim_settings = ssc( ssc_id )
168
+ mc_hash = cc( cc_id )
169
+ im_hash = imc( imc_id )
170
+ # Create and return the simulation
171
+ sim = net_inst.simulation **sim_settings.merge( initial_marking: im_hash,
172
+ marking_clamps: mc_hash
173
+ ).merge( nn )
174
+ @simulations[ key ] = sim
175
+ end
176
+ end # module YPetri::World::SimulationRelated
@@ -0,0 +1,27 @@
1
+ # As the name suggests, represents the world. Holds places, transitions, nets
2
+ # and other assets needed to set up and simulate Petri nets (settings, clamps,
3
+ # initial markings etc.). Provides basic methods to do what is necessary.
4
+ # More ergonomic and DSL-like methods are up to the YPetri::Agent.
5
+ #
6
+ class YPetri::World
7
+ include NameMagic
8
+
9
+ require_relative 'world/dependency'
10
+ require_relative 'world/petri_net_related'
11
+ require_relative 'world/simulation_related'
12
+
13
+ include self::PetriNetRelated
14
+ include self::SimulationRelated
15
+
16
+ def initialize
17
+ # Parametrize the Place / Transition / Net classes.
18
+ param_class!( { Place: YPetri::Place,
19
+ Transition: YPetri::Transition,
20
+ Net: YPetri::Net },
21
+ with: { world: self } )
22
+ # Make them their own namespaces.
23
+ [ Place(), Transition(), Net() ].each &:namespace!
24
+ # And proceeed as usual.
25
+ super
26
+ end
27
+ end