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
@@ -1,303 +1,325 @@
1
1
  #! /usr/bin/ruby
2
2
  # encoding: utf-8
3
3
 
4
+ gem 'minitest'
4
5
  require 'minitest/autorun'
5
6
  require_relative '../lib/y_petri' # tested component itself
6
7
  # require 'y_petri'
7
8
  # require 'sy'
8
9
 
9
- describe YPetri::Simulation do
10
- before do
11
- @w = YPetri::World.new
12
- end
13
-
14
- it "should allow for creation of an empty simulation" do
15
- net = @w.Net.send :new
16
- sim = net.simulation
17
- sim.pp.must_equal []
18
- sim.pp( *[] ).must_equal []
19
- sim.tt.must_equal( [] )
20
- sim.tt( *[] ).must_equal []
21
- end
22
-
23
- describe "simulation setup" do
24
- before do
25
- @p = @w.Place.send :new, name: :A, default_marking: 1
26
- @q = @w.Place.send :new, name: :B, default_marking: 2
27
- @net = @w.Net.of [ @p, @q ]
28
- end
29
-
30
- it "should allow to set up a simplistic simulation instance" do
31
- @net.simulation
32
- @net.simulation marking_clamps: { @q => 42 } # one clamp
33
- @net.simulation initial_marking: { @p => 42, @q => 43 }
34
- @net.simulation marking_clamps: { @p => 42 }, initial_marking: { @q => 43 }
35
- @net.simulation initial_marking: { A: 42 }
36
- end
37
-
38
- it "should fail with malformed arguments" do
39
- -> { @net.simulation use_default_marking: false }.must_raise TypeError
40
- -> { @net.simulation initial_marking: { Foo: 1 } }.must_raise NameError
41
- end
42
-
43
- describe "place representation aspects" do
44
- before do
45
- @s = YPetri::Simulation.new( net: @net,
46
- initial_marking: { A: 42 },
47
- marking_clamps: { B: 43 } )
48
- end
49
-
50
- it "should have elements/access" do
51
- @s.send( :place, :A )
52
- .must_be_kind_of YPetri::Simulation::PlaceRepresentation
53
- @s.send( :place, :B )
54
- .must_be_kind_of YPetri::Simulation::PlaceRepresentation
55
- @s.net.places.names.must_equal [:A, :B]
56
- @s.pn.must_equal [:A, :B]
57
- @s.send( :places ).free.size.must_equal 1
58
- @s.send( :places ).first.quantum.must_equal 1
59
- @s.send( :free_places ).names.must_equal [:A]
60
- @s.send( :places ).clamped.size.must_equal 1
61
- @s.send( :clamped_places ).names.must_equal [:B]
62
- @s.send( :places, [:A] ).map( &:source ).must_equal [@p]
63
- @s.send( :transitions, [] ).must_equal []
64
- @s.send( :places, [:A] ).map( &:source ).must_equal [@p]
65
- @s.send( :places, [] ).must_equal []
66
- end
67
-
68
- describe "marking vector representation" do
69
- it "should work" do
70
- @s.instance_variable_get( :@m_vector ).must_equal @s.m_vector
71
- @s.m_vector.must_be_kind_of YPetri::Simulation::MarkingVector
72
- @s.m_vector.size.must_equal 2
73
- @s.m_vector.to_a.must_equal [42, 43]
74
- @s.m.must_equal [42, 43]
75
- @s.marking.must_equal [42]
76
- @s.marking_clamps.keys_to_names.must_equal( { B: 43 } )
77
- end
78
- end
79
- end # describe simulation step
80
-
81
- describe "transition representation aspects" do
82
- before do
83
- @ts = @w.Transition.send :new, name: "T_ts", codomain: :A, action: -> { 1 }
84
- @tS = @w.Transition.send :new, name: "T_tS", s: { B: -1, A: 1 }, action: proc { 1 }
85
- @Ts = @w.Transition.send :new, name: "T_Ts", codomain: :A, rate: -> { 1 }
86
- @TS = @w.Transition.send :new, name: "T_TS", s: { B: -1, A: 1 }, rate: proc { 1 }
87
- end
88
-
89
- it "should be what intended" do
90
- @ts.type.must_equal :ts
91
- @ts.domain.must_equal []
92
- @ts.codomain.must_equal [@p]
93
- @tS.type.must_equal :tS
94
- @tS.domain.must_equal [@q] # inferred
95
- @tS.codomain.must_equal [@q, @p]
96
- @Ts.type.must_equal :Ts
97
- @Ts.domain.must_equal []
98
- @Ts.codomain.must_equal [@p]
99
- @TS.type.must_equal :TS
100
- @TS.domain.must_equal [@q] # inferred
101
- @TS.codomain.must_equal [@q, @p]
102
- end
103
-
104
- describe "ts transition" do
105
- before do
106
- @net = @w.Net.of [ @p, @q, @ts ]
107
- end
108
-
109
- describe "no clamps" do
110
- before do
111
- @sim = @net.simulation net: @net
112
- end
113
-
114
- it "should behave" do
115
- @sim.tt.size.must_equal 1
116
- @ts.codomain.names.must_equal [:A]
117
- @sim.ts_tt.first.codomain.names.must_equal [:A]
118
- @ts.domain.names.must_equal []
119
- @sim.ts_tt.first.domain.names.must_equal []
120
- @sim.timed?.must_equal false
121
- @sim.m.must_equal [1, 2]
122
- @sim.p_m.must_equal( { A: 1, B: 2 } )
123
- @sim.recording.must_equal( { 0 => [1, 2]} )
124
- @sim.simulation_method.must_equal :pseudo_euler
125
- @sim.core.must_be_kind_of YPetri::Core
126
- @sim.ts_tt.first.domain.must_equal []
127
- @sim.send( :ts_transitions ).first.domain_access_code.must_equal ''
128
- λ = @sim.send( :transitions ).ts.first.delta_closure
129
- λ.arity.must_equal 0
130
- λ.call.must_equal 1
131
- cc = @sim.send( :transitions ).ts.delta_closures
132
- cc.map( &:call ).must_equal [1]
133
- cl = @sim.send( :transitions ).ts.delta_closure
134
- cl.call.must_equal Matrix[ [1], [0] ]
135
- @sim.step!
136
- @sim.p_m.must_equal( { A: 2, B: 2 } ) # marking of A goes up by 1
137
- @sim.recording.must_equal( { 0 => [1, 2], 1 => [2, 2] } )
138
- end
139
- end
140
-
141
- describe "with clamps" do
142
- before do
143
- @sim = @net.simulation marking_clamps: { B: 42 }
144
- end
145
-
146
- it "should behave" do
147
- @sim.recording.must_equal( { 0 => [1] } )
148
- @sim.step!
149
- @sim.recording.must_equal( { 0 => [1], 1 => [2] } )
150
- end
151
- end
152
- end # ts transition
153
-
154
- describe "tS transition" do
155
- before do
156
- @net = @w.Net.of [ @p, @q, @tS ]
157
- end
158
-
159
- describe "no clamps" do
160
- before do
161
- @sim = @net.simulation net: @net
162
- end
163
-
164
- it "should behave" do
165
- @sim.recording.must_equal( { 0 => [1, 2] } )
166
- @sim.step!
167
- @sim.recording.must_equal( { 0 => [1, 2], 1 => [2, 1] } )
168
- end
169
- end
170
-
171
- describe "with clamps" do
172
- before do
173
- @sim = @net.simulation marking_clamps: { B: 43 }
174
- end
175
-
176
- it "should behave" do
177
- @sim.recording.must_equal( { 0 => [1] } )
178
- 3.times do @sim.step! end
179
- @sim.recording.must_equal( { 0 => [1], 1 => [2], 2 => [3], 3 => [4] } )
180
- end
181
- end
182
- end # tS transition
183
-
184
- describe "Ts transition" do
185
- before do
186
- @net = @w.Net.of [ @p, @q, @Ts ]
187
- end
188
-
189
- describe "no clamps" do
190
- before do
191
- @sim = @net.simulation sampling: 1
192
- end
193
-
194
- it "should behave" do
195
- @sim.timed?.must_equal true
196
- @sim.simulation_method.must_equal :pseudo_euler
197
- @sim.Ts_tt.size.must_equal 1
198
- @sim.send( :transitions ).Ts.first.gradient_closure.call.must_equal 1
199
- @sim.Ts_tt.first.codomain.names.must_equal [:A]
200
- @sim.recording.must_equal( { 0.0 => [1, 2] } )
201
- @sim.step! 1
202
- @sim.recording.must_equal( { 0.0 => [1, 2], 1.0 => [2, 2] } )
203
- end
204
- end
205
-
206
- describe "with clamps" do
207
- before do
208
- @sim = @net.simulation sampling: 1, marking_clamps: { B: 43 }
209
- end
210
-
211
- it "should behave" do
212
- @sim.recording.must_equal( { 0.0 => [1] } )
213
- 3.times do @sim.step! 1 end
214
- @sim.recording.must_equal( { 0.0 => [1], 1.0 => [2], 2.0 => [3], 3.0 => [4] } )
215
- end
216
- end
217
- end # Ts transition
218
-
219
- describe "TS transition" do
220
- before do
221
- @net = @w.Net.of [ @p, @q, @TS ]
222
- end
223
-
224
- describe "no clamps" do
225
- before do
226
- @sim = @net.simulation sampling: 1
227
- end
228
-
229
- it "should behave" do
230
- @sim.recording.must_be_kind_of YPetri::Net::DataSet
231
- @sim.recording
232
- .must_equal @net.State.marking.new_dataset.update( 0.0 => [1, 2] )
233
- @sim.recording.must_equal( { 0.0 => [1, 2] } )
234
- @sim.step! 1
235
- @sim.recording.must_equal( { 0.0 => [1, 2], 1.0 => [2, 1] } )
236
- end
237
- end
238
-
239
- describe "with clamps" do
240
- before do
241
- @sim = @net.simulation sampling: 1, marking_clamps: { B: 43 }
242
- end
243
-
244
- it "should behave" do
245
- @sim.recording.must_equal( { 0.0 => [1] } )
246
- 3.times do @sim.step! end
247
- @sim.recording.must_equal( { 0.0 => [1], 1.0 => [2], 2.0 => [3], 3.0 => [4] } )
248
- end
249
- end
250
- end # TS transition
251
- end # transition representation aspects
252
- end
253
- end
254
-
255
- describe "timeless simulation" do
256
- before do
257
- self.class.class_exec { include YPetri }
258
- U = Place m!: 2.5
259
- V = Place m!: 2.5
260
- Uplus = Transition codomain: :U do 1 end # s transition
261
- U2V = Transition s: { U: -1, V: 1 } # S transition
262
- set_ssc :Timeless, YPetri::Simulation::DEFAULT_SETTINGS.call
263
- new_simulation ssc: :Timeless
264
- 5.times do simulation.step! end
265
- end
266
-
267
- it "should behave" do
268
- s = simulation
269
- assert ! s.timed?
270
- s.core.must_be_kind_of YPetri::Core::Timeless::PseudoEuler
271
- ds = s.recording
272
- ds.size.must_equal 6
273
- ds.events.must_equal [0, 1, 2, 3, 4, 5]
274
- ds.interpolate( 1 )
275
- .must_equal [2.5, 3.5]
276
- ds.interpolate( 2 )
277
- .must_equal [2.5, 4.5]
278
- -> { ds.interpolate( 1.5 ) }.must_raise TypeError
279
- ds.reconstruct( event: 2 )
280
- .p_m.must_equal( { U: 2.5, V: 4.5 } )
281
- ds.reconstruct( event: 2 ).must_respond_to( :pm )
282
- ds.marking.slice( 2..4 ).series
283
- .must_equal [[2.5, 2.5, 2.5], [4.5, 5.5, 6.5]]
284
- ds.marking.slice( 2..4 )
285
- .must_equal( { 2 => [2.5, 4.5],
286
- 3 => [2.5, 5.5],
287
- 4 => [2.5, 6.5] } )
288
- ds.firing.slice( 1..2 ).series
289
- .must_equal [[1, 1]]
290
- ds.series( firing: [:U2V] )
291
- .must_equal [ [ 1, 1, 1, 1, 1, 1 ] ]
292
- ds.delta( [:U], transitions: [:Uplus] ).series
293
- .must_equal [ [ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ] ]
294
- tmp = ds.reduce_features( marking: [:U], firing: [:U2V] )
295
- tmp.features
296
- .must_equal( ds.net.State.features marking: [:U], firing: [:U2V] )
297
- tmp.must_equal( { 0 => [2.5, 1], 1 => [2.5, 1], 2 => [2.5, 1],
298
- 3 => [2.5, 1], 4 => [2.5, 1], 5 => [2.5, 1] } )
299
- end
300
- end
10
+ # describe YPetri::Simulation do
11
+ # before do
12
+ # @w = YPetri::World.new
13
+ # end
14
+
15
+ # it "should allow for creation of an empty simulation" do
16
+ # net = @w.Net.send :new
17
+ # sim = net.simulation
18
+ # skip
19
+ # sim.pp.must_equal []
20
+ # sim.pp( *[] ).must_equal []
21
+ # sim.tt.must_equal( [] )
22
+ # sim.tt( *[] ).must_equal []
23
+ # end
24
+
25
+ # describe "simulation setup" do
26
+ # before do
27
+ # @p = @w.Place.send :new, name: :A, default_marking: 1
28
+ # @q = @w.Place.send :new, name: :B, default_marking: 2
29
+ # @net = @w.Net.of [ @p, @q ]
30
+ # end
31
+
32
+ # it "should allow to set up a simplistic simulation instance" do
33
+ # @net.simulation
34
+ # @net.simulation marking_clamps: { @q => 42 } # one clamp
35
+ # @net.simulation initial_marking: { @p => 42, @q => 43 }
36
+ # @net.simulation marking_clamps: { @p => 42 }, initial_marking: { @q => 43 }
37
+ # @net.simulation initial_marking: { A: 42 }
38
+ # end
39
+
40
+ # it "should fail with malformed arguments" do
41
+ # -> { @net.simulation use_default_marking: false }.must_raise TypeError
42
+ # -> { @net.simulation initial_marking: { Foo: 1 } }.must_raise NameError
43
+ # end
44
+
45
+ # describe "place representation aspects" do
46
+ # before do
47
+ # @s = YPetri::Simulation.new( net: @net,
48
+ # initial_marking: { A: 42 },
49
+ # marking_clamps: { B: 43 } )
50
+ # end
51
+
52
+ # it "should have elements/access" do
53
+ # @s.send( :place, :A )
54
+ # .must_be_kind_of YPetri::Simulation::PlaceRepresentation
55
+ # @s.send( :place, :B )
56
+ # .must_be_kind_of YPetri::Simulation::PlaceRepresentation
57
+ # @s.net.places.names.must_equal [:A, :B]
58
+ # @s.pn.must_equal [:A, :B]
59
+ # @s.send( :places ).free.size.must_equal 1
60
+ # @s.send( :places ).first.quantum.must_equal 1
61
+ # @s.send( :free_places ).names.must_equal [:A]
62
+ # @s.send( :places ).clamped.size.must_equal 1
63
+ # @s.send( :clamped_places ).names.must_equal [:B]
64
+ # @s.send( :Places, [:A] ).map( &:source ).must_equal [@p]
65
+ # @s.send( :places, :A ).map( &:source ).must_equal [@p]
66
+ # @s.send( :Transitions, [] ).must_equal []
67
+ # @s.send( :Places, [] ).must_equal []
68
+ # end
69
+
70
+ # describe "marking vector representation" do
71
+ # it "should work" do
72
+ # @s.instance_variable_get( :@m_vector ).must_equal @s.m_vector
73
+ # @s.m_vector.must_be_kind_of YPetri::Simulation::MarkingVector
74
+ # @s.m_vector.size.must_equal 2
75
+ # @s.m_vector.to_a.must_equal [42, 43]
76
+ # @s.m.must_equal [42, 43]
77
+ # @s.marking.must_equal [42]
78
+ # @s.marking_clamps.keys_to_names.must_equal( { B: 43 } )
79
+ # end
80
+ # end
81
+ # end # describe simulation step
82
+
83
+ # describe "transition representation aspects" do
84
+ # before do
85
+ # @ts = @w.Transition.send :new, name: "T_ts", codomain: :A, action: -> { 1 }
86
+ # @tS = @w.Transition.send :new, name: "T_tS", s: { B: -1, A: 1 }, action: proc { 1 }
87
+ # @Ts = @w.Transition.send :new, name: "T_Ts", codomain: :A, rate: -> { 1 }
88
+ # @TS = @w.Transition.send :new, name: "T_TS", s: { B: -1, A: 1 }, rate: proc { 1 }
89
+ # end
90
+
91
+ # it "should be what intended" do
92
+ # @ts.type.must_equal :ts
93
+ # @ts.domain.must_equal []
94
+ # @ts.codomain.must_equal [@p]
95
+ # @tS.type.must_equal :tS
96
+ # @tS.domain.must_equal [@q] # inferred
97
+ # @tS.codomain.must_equal [@q, @p]
98
+ # @Ts.type.must_equal :Ts
99
+ # @Ts.domain.must_equal []
100
+ # @Ts.codomain.must_equal [@p]
101
+ # @TS.type.must_equal :TS
102
+ # @TS.domain.must_equal [@q] # inferred
103
+ # @TS.codomain.must_equal [@q, @p]
104
+ # end
105
+
106
+ # describe "ts transition" do
107
+ # before do
108
+ # @net = @w.Net.of [ @p, @q, @ts ]
109
+ # end
110
+
111
+ # describe "no clamps" do
112
+ # before do
113
+ # @sim = @net.simulation net: @net
114
+ # end
115
+
116
+ # it "should behave" do
117
+ # @sim.tt.size.must_equal 1
118
+ # @ts.codomain.names.must_equal [:A]
119
+ # @sim.ts_tt.first.codomain.names.must_equal [:A]
120
+ # @ts.domain.names.must_equal []
121
+ # @sim.ts_tt.first.domain.names.must_equal []
122
+ # @sim.timed?.must_equal false
123
+ # @sim.m.must_equal [1, 2]
124
+ # @sim.p_m.must_equal( { A: 1, B: 2 } )
125
+ # @sim.recording.must_equal( { 0 => [1, 2]} )
126
+ # @sim.simulation_method.must_equal :pseudo_euler
127
+ # @sim.core.must_be_kind_of YPetri::Core
128
+ # @sim.ts_tt.first.domain.must_equal []
129
+ # @sim.send( :ts_transitions ).first.domain_access_code.must_equal ''
130
+ # λ = @sim.send( :transitions ).ts.first.delta_closure
131
+ # λ.arity.must_equal 0
132
+ # λ.call.must_equal [1]
133
+ # cc = @sim.send( :transitions ).ts.delta_closures
134
+ # cc.map( &:call ).map( &:first ).must_equal [1]
135
+ # cl = @sim.send( :transitions ).ts.delta_closure
136
+ # cl.call.must_equal Matrix[ [1], [0] ]
137
+ # @sim.step!
138
+ # @sim.p_m.must_equal( { A: 2, B: 2 } ) # marking of A goes up by 1
139
+ # @sim.recording.must_equal( { 0 => [1, 2], 1 => [2, 2] } )
140
+ # end
141
+ # end
142
+
143
+ # describe "with clamps" do
144
+ # before do
145
+ # @sim = @net.simulation marking_clamps: { B: 42 }
146
+ # end
147
+
148
+ # it "should behave" do
149
+ # @sim.recording.must_equal( { 0 => [1] } )
150
+ # @sim.step!
151
+ # @sim.recording.must_equal( { 0 => [1], 1 => [2] } )
152
+ # end
153
+ # end
154
+ # end # ts transition
155
+
156
+ # describe "tS transition" do
157
+ # before do
158
+ # @net = @w.Net.of [ @p, @q, @tS ]
159
+ # end
160
+
161
+ # describe "no clamps" do
162
+ # before do
163
+ # @sim = @net.simulation net: @net
164
+ # end
165
+
166
+ # it "should behave" do
167
+ # @sim.recording.must_equal( { 0 => [1, 2] } )
168
+ # @sim.step!
169
+ # @sim.recording.must_equal( { 0 => [1, 2], 1 => [2, 1] } )
170
+ # end
171
+ # end
172
+
173
+ # describe "with clamps" do
174
+ # before do
175
+ # @sim = @net.simulation marking_clamps: { B: 43 }
176
+ # end
177
+
178
+ # it "should behave" do
179
+ # @sim.recording.must_equal( { 0 => [1] } )
180
+ # 3.times do @sim.step! end
181
+ # @sim.recording.must_equal( { 0 => [1], 1 => [2], 2 => [3], 3 => [4] } )
182
+ # end
183
+ # end
184
+ # end # tS transition
185
+
186
+ # describe "Ts transition" do
187
+ # before do
188
+ # @net = @w.Net.of [ @p, @q, @Ts ]
189
+ # end
190
+
191
+ # describe "no clamps" do
192
+ # before do
193
+ # @sim = @net.simulation sampling: 1
194
+ # end
195
+
196
+ # it "should behave" do
197
+ # @sim.timed?.must_equal true
198
+ # @sim.simulation_method.must_equal :pseudo_euler
199
+ # @sim.Ts_tt.size.must_equal 1
200
+ # @sim.send( :transitions ).Ts.first.gradient_closure.call.must_equal [1]
201
+ # @sim.Ts_tt.first.codomain.names.must_equal [:A]
202
+ # @sim.recording.must_equal( { 0.0 => [1, 2] } )
203
+ # @sim.step! 1
204
+ # @sim.recording.must_equal( { 0.0 => [1, 2], 1.0 => [2, 2] } )
205
+ # end
206
+ # end
207
+
208
+ # describe "with clamps" do
209
+ # before do
210
+ # @sim = @net.simulation sampling: 1, marking_clamps: { B: 43 }
211
+ # end
212
+
213
+ # it "should behave" do
214
+ # @sim.send( :transitions ).Ts.first.codomain.names.must_equal [:A]
215
+ # @sim.simulation_method.must_equal :pseudo_euler
216
+ # @sim.timed?.must_equal true
217
+ # @sim.core.timed?.must_equal true
218
+ # @sim.reset!
219
+ # @sim.time.must_equal 0
220
+ # @sim.p_m.must_equal( { A: 1, B: 43 } )
221
+ # @sim.recording.must_equal( { 0.0 => [1] } )
222
+ # @sim.send( :transitions ).Ts.first.gradient_closure.call.must_equal [1]
223
+ # @sim.step! 1
224
+ # @sim.time.must_equal 1
225
+ # @sim.p_m.must_equal( { A: 2, B: 43 } )
226
+ # @sim.recording.to_h.must_equal( { 0.0 => [1], 1.0 => [2] } )
227
+ # @sim.send( :transitions ).Ts.first.gradient_closure.call.must_equal [1]
228
+ # @sim.step! 1
229
+ # @sim.time.must_equal 2
230
+ # @sim.p_m.must_equal( { A: 3, B: 43 } )
231
+ # @sim.recording.to_h.must_equal( { 0.0 => [1], 1.0 => [2], 2.0 => [3] } )
232
+ # @sim.send( :transitions ).Ts.first.gradient_closure.call.must_equal [1]
233
+
234
+ # 3.times do @sim.step! 1 end
235
+ # @sim.recording.to_h
236
+ # .must_equal( { 0.0 => [1], 1.0 => [2], 2.0 => [3], 3.0 => [4] } )
237
+ # end
238
+ # end
239
+ # end # Ts transition
240
+
241
+ # describe "TS transition" do
242
+ # before do
243
+ # @net = @w.Net.of [ @p, @q, @TS ]
244
+ # end
245
+
246
+ # describe "no clamps" do
247
+ # before do
248
+ # @sim = @net.simulation sampling: 1
249
+ # end
250
+
251
+ # it "should behave" do
252
+ # @sim.recording.must_be_kind_of YPetri::Net::DataSet
253
+ # @sim.recording
254
+ # .must_equal @net.State.Features.marking.DataSet.new.update( 0.0 => [1, 2] )
255
+ # @sim.recording.must_equal( { 0.0 => [1, 2] } )
256
+ # @sim.step! 1
257
+ # @sim.recording.must_equal( { 0.0 => [1, 2], 1.0 => [2, 1] } )
258
+ # end
259
+ # end
260
+
261
+ # describe "with clamps" do
262
+ # before do
263
+ # @sim = @net.simulation sampling: 1, marking_clamps: { B: 43 }
264
+ # end
265
+
266
+ # it "should behave" do
267
+ # @sim.recording.must_equal( { 0.0 => [1] } )
268
+ # 3.times do @sim.step! end
269
+ # @sim.recording.must_equal( { 0.0 => [1], 1.0 => [2], 2.0 => [3], 3.0 => [4] } )
270
+ # end
271
+ # end
272
+ # end # TS transition
273
+ # end # transition representation aspects
274
+ # end
275
+ # end
276
+
277
+ # describe "timeless simulation" do
278
+ # before do
279
+ # self.class.class_exec { include YPetri }
280
+ # U = Place m!: 2.5
281
+ # V = Place m!: 2.5
282
+ # Uplus = Transition codomain: :U do 1 end # s transition
283
+ # U2V = Transition s: { U: -1, V: 1 } # S transition
284
+ # set_ssc :Timeless, YPetri::Simulation::DEFAULT_SETTINGS.call
285
+ # new_simulation ssc: :Timeless
286
+ # 5.times do simulation.step! end
287
+ # end
288
+
289
+ # it "should behave" do
290
+ # s = simulation
291
+ # assert ! s.timed?
292
+ # s.core.must_be_kind_of YPetri::Core::Timeless::PseudoEuler
293
+ # ds = s.recording
294
+ # ds.size.must_equal 6
295
+ # ds.events.must_equal [0, 1, 2, 3, 4, 5]
296
+ # ds.interpolate( 1 )
297
+ # .must_equal [2.5, 3.5]
298
+ # ds.interpolate( 2 )
299
+ # .must_equal [2.5, 4.5]
300
+ # -> { ds.interpolate( 1.5 ) }.must_raise TypeError
301
+ # ds.reconstruct( at: 2 )
302
+ # .p_m.must_equal( { U: 2.5, V: 4.5 } )
303
+ # ds.reconstruct( at: 2 ).must_respond_to( :pm )
304
+ # ds.marking.slice( 2..4 ).series
305
+ # .must_equal [[2.5, 2.5, 2.5], [4.5, 5.5, 6.5]]
306
+ # ds.marking.slice( 2..4 )
307
+ # .must_equal( { 2 => [2.5, 4.5],
308
+ # 3 => [2.5, 5.5],
309
+ # 4 => [2.5, 6.5] } )
310
+ # ds.firing.slice( 1..2 ).series
311
+ # .must_equal [[1, 1]]
312
+ # ds.series( firing: [:U2V] )
313
+ # .must_equal [ [ 1, 1, 1, 1, 1, 1 ] ]
314
+ # ds.Delta( [:U], transitions: [:Uplus] ).series
315
+ # .must_equal [ [ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ] ]
316
+ # tmp = ds.reduce_features( marking: [:U], firing: [:U2V] )
317
+ # tmp.features
318
+ # .must_equal( ds.net.State.Features marking: [:U], firing: [:U2V] )
319
+ # tmp.must_equal( { 0 => [2.5, 1], 1 => [2.5, 1], 2 => [2.5, 1],
320
+ # 3 => [2.5, 1], 4 => [2.5, 1], 5 => [2.5, 1] } )
321
+ # end
322
+ # end
301
323
 
302
324
  describe "timed simulation" do
303
325
  before do
@@ -311,44 +333,49 @@ describe "timed simulation" do
311
333
 
312
334
  it "should behave" do
313
335
  places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected
314
- simulation.tap do |s|
315
- s.settings.must_equal( { method: :pseudo_euler, guarded: false,
316
- step: 0.1, sampling: 5, time: 0..60 } )
317
- assert s.recording.to_csv.start_with?( "0.0,0.5,0.5\n" +
318
- "5.0,0.475,0.38916\n" +
319
- "10.0,0.45,0.30289\n" +
320
- "15.0,0.425,0.23574\n" +
321
- "20.0,0.4,0.18348\n" +
322
- "25.0,0.375,0.1428\n" )
323
- assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" )
324
- s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0,
325
- 25.0, 30.0, 35.0, 40.0, 45.0,
326
- 50.0, 55.0, 60.0 ]
327
- s.recording.values_at( 5, 10 )
328
- .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ]
329
- s.recording.slice( 2..12 )
330
- .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } )
331
- s.recording.net
332
- .must_equal net
333
- s.recording.features
334
- .must_equal net.State.marking( [:A, :B] )
335
- net.State.Features.State
336
- .must_equal net.State
337
- s.recording.State
338
- .must_equal net.State
339
- s.recording.series( marking: [:A] )
340
- .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325,
341
- 0.3, 0.275, 0.25, 0.225, 0.2 ] ]
342
- s.recording.firing.series
343
- .must_equal []
344
- s.recording.firing
345
- .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 )
346
- s.recording
347
- .delta( [:A], transitions: [:A_pump], delta_time: 0.1 )
348
- .series
349
- .must_equal [ [ -0.0005 ] * 13 ]
350
- plot_state
351
- sleep 5
352
- end
336
+ s = simulation
337
+ s.settings.must_equal( { method: :pseudo_euler, guarded: false,
338
+ step: 0.1, sampling: 5, time: 0..60 } )
339
+ assert s.recording.to_csv.start_with?( ":event,:A,:B\n" +
340
+ "0.0,0.5,0.5\n" +
341
+ "5.0,0.475,0.38916\n" +
342
+ "10.0,0.45,0.30289\n" +
343
+ "15.0,0.425,0.23574\n" +
344
+ "20.0,0.4,0.18348\n" +
345
+ "25.0,0.375,0.1428\n" )
346
+ assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" )
347
+ s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0,
348
+ 25.0, 30.0, 35.0, 40.0, 45.0,
349
+ 50.0, 55.0, 60.0 ]
350
+ s.recording.values_at( 5, 10 )
351
+ .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ]
352
+ s.recording.slice( 2..12 )
353
+ .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } )
354
+ s.recording.net
355
+ .must_equal net
356
+ s.recording.features
357
+ .must_equal net.State.Features.marking( :A, :B )
358
+ net.State.Features.State
359
+ .must_equal net.State
360
+ s.recording.net.State
361
+ .must_equal net.State
362
+ s.recording.series( marking: [:A] )
363
+ .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325,
364
+ 0.3, 0.275, 0.25, 0.225, 0.2 ] ]
365
+ s.net.State.Features.firing.map( &:transition ).names
366
+ .must_equal [ :A_pump, :B_decay ]
367
+ s.recording.reduce_features( s.net.State.Features.firing, Δt: 1 )
368
+ .to_h.take( 2 ).map( &:flatten! ).map { |a| a.map &[:round, 6 ] }
369
+ .must_equal [ [ 0.0, 0.005, 0.025 ], [ 5.0, 0.005, 0.019458 ] ]
370
+ s.recording.firing( Δt: 0.1 ).series.map( &:first ).map( &[ :round, 6 ] )
371
+ .must_equal [ 0.0005, 0.0025 ]
372
+ s.recording.Firing( [] )
373
+ .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 )
374
+ s.recording
375
+ .delta( :A, transitions: [:A_pump], delta_time: 0.1 )
376
+ .series
377
+ .must_equal [ [ -0.0005 ] * 13 ]
378
+ plot_state
379
+ sleep 5
353
380
  end
354
381
  end