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
data/test/net_test.rb CHANGED
@@ -1,6 +1,7 @@
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'
@@ -27,12 +28,12 @@ describe YPetri::Net do
27
28
 
28
29
  it "should be able to include places" do
29
30
  p = @w.Place.send :new, name: "A", quantum: 0.1, marking: 1.1
30
- @net.includes_place?( p ).must_equal false
31
- @net.include_place p
31
+ @net.include_place?( p ).must_equal false
32
+ @net.include_place( p ).must_equal true
32
33
  @net.places.must_equal [ p ]
33
34
  @net.place( :A ).must_equal p
34
- @net.places( [] ).must_equal []
35
- @net.places( [:A] ).must_equal [ p ]
35
+ @net.Places( [] ).must_equal []
36
+ @net.places( :A ).must_equal [ p ]
36
37
  end
37
38
  end
38
39
 
@@ -50,9 +51,9 @@ describe YPetri::Net do
50
51
  end
51
52
 
52
53
  it "should expose its elements" do
53
- assert_equal [@p1, @p2, @p3], @net.places
54
- assert_equal [:A, :B, :C], @net.pn
55
- assert_equal [], @net.transitions
54
+ @net.places.must_equal [ @p1, @p2, @p3 ]
55
+ @net.pn.must_equal [ :A, :B, :C ]
56
+ @net.transitions.must_equal []
56
57
  end
57
58
 
58
59
  it "should allow only right transitions to be included in it" do
@@ -70,17 +71,18 @@ describe YPetri::Net do
70
71
  it "should be able to tell its qualities" do
71
72
  assert_equal false, @net.functional?
72
73
  assert_equal false, @net.timed?
73
- assert @net.include?( @p1 ) && !@net.include?( YPetri::Place.send :new )
74
+ assert @net.include?( @p1 )
75
+ assert ! @net.include?( YPetri::Place.send :new )
74
76
  end
75
77
 
76
- it "should know its state and marking features" do
77
- @net.state.must_equal [ @p1, @p2, @p3 ].map( &:marking )
78
+ it "should know its state (marking owned by the places)" do
78
79
  @net.state.must_be_kind_of YPetri::Net::State
80
+ @net.state.must_equal [ @p1, @p2, @p3 ].map( &:marking )
79
81
  @net.marking.must_equal [ @p1, @p2, @p3 ].map( &:marking )
80
82
  @net.marking.must_be_kind_of Array
81
83
  end
82
84
 
83
- it "should have standard equipment of a class" do
85
+ it "should have standard equipment expected of a class" do
84
86
  assert @net == @net.dup
85
87
  assert @net.inspect.start_with? "#<Net:"
86
88
  end
@@ -97,12 +99,12 @@ describe YPetri::Net do
97
99
  assert_equal [ @t1 ], @net.transitions
98
100
  assert_equal [ :T1 ], @net.tn
99
101
  @net.transition( :T1 ).must_equal @t1
100
- @net.transitions( [] ).must_equal []
101
- @net.transitions( [ :T1 ] ).must_equal [ @t1 ]
102
- @net.element( :T1 ).must_equal @t1
103
- @net.elements( [] ).must_equal []
104
- @net.elements( [ :T1 ] ).must_equal [ @t1 ]
105
- @net.elements( [ :A, :T1 ] ).must_equal [ @p1, @t1 ]
102
+ @net.Transitions( [] ).must_equal []
103
+ @net.transitions( :T1 ).must_equal [ @t1 ]
104
+ @net.node( :T1 ).must_equal @t1
105
+ @net.Nodes( [] ).must_equal []
106
+ @net.nodes( :T1 ).must_equal [ @t1 ]
107
+ @net.nodes( :A, :T1 ).must_equal [ @p1, @t1 ]
106
108
  end
107
109
 
108
110
  it "should expose transition groups" do
@@ -119,7 +121,7 @@ describe YPetri::Net do
119
121
  it "should have #place & #transition for safe access to them" do
120
122
  @net.send( :place, @p1 ).must_equal @p1
121
123
  @net.send( :transition, @t1 ).must_equal @t1
122
- @net.send( :element, @p1 ).must_equal @p1
124
+ @net.send( :node, @p1 ).must_equal @p1
123
125
  end
124
126
 
125
127
  it "has #new_simulation & #new_timed_simulation constructors" do
@@ -185,65 +187,466 @@ describe YPetri::Net do
185
187
  end
186
188
 
187
189
 
188
- describe YPetri::Net::State do
190
+ describe "state, features, record and dataset" do
189
191
  before do
190
192
  @w = YPetri::World.new
191
193
  @net = @w.Net.send :new
194
+ @net << @w.Place.send( :new, ɴ: :A, m!: 2 )
195
+ @net << @w.Place.send( :new, ɴ: :B, m!: 3 )
196
+ @net << @w.Place.send( :new, ɴ: :C, m!: 4 )
197
+ # TS transitions A2B, A_plus
198
+ @net << @w.Transition.send( :new, ɴ: :A2B, s: { A: -1, B: 1 }, rate: 0.01 )
199
+ @net << @w.Transition.send( :new, ɴ: :A_plus, domain: :A, s: { A: 1 }, rate: -> a { a * 0.001 } )
200
+ # tS transitions A2B_s, A_plus_t
201
+ @net << @w.Transition.send( :new, ɴ: :A2B_t, s: { A: -1, B: 1 }, action: proc { 0.42 } )
202
+ @net << @w.Transition.send( :new, ɴ: :A_plus_t, s: { A: 1 }, action: -> { 0.42 } )
203
+ # Ts transition
204
+ @net << @w.Transition.send( :new, ɴ: :C_plus, domain: [:A, :B], codomain: :C,
205
+ rate: -> a, b { a * 0.001 + b ** 2 * 0.0002 } )
206
+ # ts transition
207
+ @net << @w.Transition.send( :new, ɴ: :C_minus, domain: :C, codomain: :C,
208
+ action: -> c { - c * 0.5 } )
209
+ # A transition
210
+ @net << @w.Transition.send( :new, ɴ: :C_to_42, codomain: :C,
211
+ assignment: -> { 42 } )
192
212
  end
193
213
 
194
- it "should be already parametrized on @w.Net" do
195
- @St = @net.State
196
- @St.net.must_equal @net
197
- assert @St.Feature < YPetri::Net::State::Feature
198
- -> { @St.feature( marking: :A ) }.must_raise NameError
214
+ describe YPetri::Net::State do
215
+ before do
216
+ @w = YPetri::World.new
217
+ @net = @w.Net.send :new
218
+ end
219
+
220
+ it "should be already a param. subclass on @w.Net" do
221
+ @St = @net.State
222
+ @St.net.must_equal @net
223
+ assert @St.Feature < YPetri::Net::State::Feature # is a PS
224
+ -> { @St.Feature( marking: :A ) }.must_raise NameError
225
+ end
199
226
  end
200
- end
201
227
 
228
+ describe YPetri::Net::State::Feature do
229
+ before do
230
+ @sim = @net.simulation step: 1.0
231
+ end
232
+
233
+ describe YPetri::Net::State::Feature::Marking do
234
+ before do
235
+ @m = @net.State.Feature.Marking( :A )
236
+ end
202
237
 
203
- describe YPetri::Net::DataSet do
204
- before do
205
- @w = YPetri::World.new
206
- @net = @w.Net.send :new
207
- @net << @w.Place.send( :new, ɴ: :A )
208
- @net << @w.Place.send( :new, ɴ: :B )
209
- @net << @w.Transition.send( :new, ɴ: :A2B, s: { A: -1, B: 1 }, rate: 0.01 )
210
- @net << @w.Transition.send( :new, ɴ: :A_plus, s: { A: 1 }, rate: 0.001 )
238
+ it "should have expected attributes" do
239
+ @m.type.must_equal :marking
240
+ @m.place.must_equal @net.place( :A )
241
+ end
242
+
243
+ it "should work" do
244
+ @m.extract_from( @sim ).must_equal 2
245
+ @m.must_equal @net.State.Feature.Marking( :A )
246
+ end
247
+ end
248
+
249
+ describe YPetri::Net::State::Feature::Flux do
250
+ before do
251
+ @f = @net.State.Feature.Flux( :A2B )
252
+ end
253
+
254
+ it "should have expected attributes" do
255
+ @f.type.must_equal :flux
256
+ @f.transition.must_equal @net.transition( :A2B )
257
+ end
258
+
259
+ it "should work" do
260
+ @f.extract_from( @sim ).must_equal 0.02
261
+ @f.must_equal @net.State.Feature.Flux( :A2B )
262
+ end
263
+ end
264
+
265
+ describe YPetri::Net::State::Feature::Firing do
266
+ before do
267
+ @fT = @net.State.Feature.Firing( :A2B )
268
+ @ft = @net.State.Feature.Firing( :A2B_t )
269
+ end
270
+
271
+ it "should have expected attributes" do
272
+ @fT.type.must_equal :firing
273
+ @ft.type.must_equal :firing
274
+ @fT.timed?.must_equal true
275
+ @ft.timed?.must_equal false
276
+ @fT.transition.must_equal @net.transition( :A2B )
277
+ @ft.transition.must_equal @net.transition( :A2B_t )
278
+ end
279
+
280
+ it "should work" do
281
+ @ft.extract_from( @sim ).must_equal 0.42
282
+ @fT.extract_from( @sim, Δt: 0.5 ).must_equal 0.01
283
+ @ft.must_equal @net.State.Feature.Firing( :A2B_t )
284
+ end
285
+ end
286
+
287
+ describe YPetri::Net::State::Feature::Gradient do
288
+ before do
289
+ @g1 = @net.State.Feature.Gradient( :A, transitions: [:A2B] )
290
+ @g2 = @net.State.Feature.Gradient( :A, transitions: [:A2B, :A_plus] )
291
+ @g3 = @net.State.Feature.Gradient( :A, transitions: :C_plus )
292
+ @g4 = @net.State.Feature.Gradient( :C, transitions: [:C_plus] )
293
+ @g5 = @net.State.Feature.Gradient( :A, transitions: [:A2B, :C_plus] )
294
+ @g6 = @net.State.Feature.Gradient( :C, transitions: [:A2B, :C_plus] )
295
+ @ga = @net.State.Feature.Gradient( :A ) # total gradient
296
+ @gc = @net.State.Feature.Gradient( :C ) # total gradient
297
+ end
298
+
299
+ it "should have expected attributes" do
300
+ assert [ @g1, @g2, @g3, @g4, @g5, @g6, @ga, @gc ].map( &:type )
301
+ .must_equal [ :gradient ] * 8
302
+ @g1.place.must_equal @net.place( :A )
303
+ @g1.transitions.must_equal @net.transitions( :A2B )
304
+ @ga.place.must_equal @net.place( :A )
305
+ @ga.tt.names.sort.must_equal [:A2B, :A_plus, :C_plus].sort # all of them
306
+ @gc.tt.names.sort.must_equal [:A2B, :A_plus, :C_plus].sort # all of them
307
+ end
308
+
309
+ it "should work" do
310
+ @g1.extract_from( @sim ).must_be_within_epsilon -0.02
311
+ @g2.extract_from( @sim ).must_be_within_epsilon -0.018
312
+ @g3.extract_from( @sim ).must_be_within_epsilon 0
313
+ @g4.extract_from( @sim ).must_be_within_epsilon 0.0038
314
+ @g5.extract_from( @sim ).must_be_within_epsilon -0.02
315
+ @g6.extract_from( @sim ).must_be_within_epsilon 0.0038
316
+ @ga.extract_from( @sim ).must_be_within_epsilon -0.018
317
+ @gc.extract_from( @sim ).must_be_within_epsilon 0.0038
318
+ @g2.must_equal @net.State.Feature.Gradient( :A, transitions: [ :A_plus, :A2B ] )
319
+ end
320
+ end
321
+
322
+ describe YPetri::Net::State::Feature::Delta do
323
+ before do
324
+ @d1T = @net.State.Feature.Delta( :A, transitions: [ :A2B ] )
325
+ @dT = @net.State.Feature.Delta( :A, transitions: @net.T_tt )
326
+ @d1t = @net.State.Feature.Delta( :A, transitions: [ :A2B_t ] )
327
+ @d2t = @net.State.Feature.Delta( :A, transitions: :A_plus_t )
328
+ @d3t = @net.State.Feature.Delta( :A, transitions: [ :C_minus ] )
329
+ @dt = @net.State.Feature.Delta( :A, transitions: @net.t_tt )
330
+ end
331
+
332
+ it "should have expected attributes" do
333
+ assert [ @d1T, @dT, @d1t, @dt ].all? { |f| f.type == :delta }
334
+ assert [ @d1T, @dT ].all? &:timed?
335
+ assert ! [ @d1t, @d2t, @dt ].any?( &:timed? )
336
+ [ @d1T, @dT, @d1t, @d2t, @d3t, @dt ].map( &:place ).names
337
+ .must_equal [ :A ] * 6
338
+ @d1T.transitions.must_equal @net.tt( :A2B )
339
+ @dT.transitions.must_equal @net.T_tt.sort_by( &:object_id )
340
+ @d1t.transitions.must_equal @net.tt( :A2B_t )
341
+ @d2t.transitions.must_equal @net.tt( :A_plus_t )
342
+ @dt.tt.names.sort.must_equal [ :A2B_t, :A_plus_t, :C_minus ].sort
343
+ end
344
+
345
+ it "should work" do
346
+ @d1T.extract_from( @sim, Δt: 1 ).must_be_within_epsilon -0.02
347
+ @d1T.extract_from( @sim, Δt: 10 ).must_be_within_epsilon -0.2
348
+ @dT.extract_from( @sim, Δt: 1 ).must_be_within_epsilon -0.018
349
+ @d1t.extract_from( @sim ).must_be_within_epsilon -0.42
350
+ @d2t.extract_from( @sim ).must_be_within_epsilon 0.42
351
+ @d3t.extract_from( @sim ).must_be_within_epsilon 0
352
+ @dt.extract_from( @sim ).must_be_within_epsilon 0
353
+ @dT.must_equal @net.State.Feature.Delta( :A, transitions: @net.T_tt.reverse )
354
+ end
355
+ end
356
+
357
+ describe YPetri::Net::State::Feature::Assignment do
358
+ before do
359
+ @af1 = @net.State.Feature.Assignment( :C, transition: :C_to_42 )
360
+ @af2 = @net.State.Feature.Assignment( :C )
361
+ end
362
+
363
+ it "should have the expected attributes" do
364
+ @af1.type.must_equal :assignment
365
+ @af2.type.must_equal :assignment
366
+ @af1.transition.must_equal @net.transition( :C_to_42 )
367
+ @af2.transition.must_equal @net.transition( :C_to_42 )
368
+ end
369
+
370
+ it "should work" do
371
+ @af1.extract_from( @sim ).must_equal 42
372
+ @af2.extract_from( @sim ).must_equal 42
373
+ @af1.must_equal @net.State.Feature.Assignment( :C )
374
+ end
375
+ end
376
+ end
377
+
378
+ describe YPetri::Net::State::Features do
379
+ before do
380
+ @sim = @net.simulation step: 1.0
381
+ @Ff = @sim.net.State.Features
382
+ end
383
+
384
+ describe "#Marking and #marking feature set constructors" do
385
+ before do
386
+ @ff1 = @Ff.Marking [ :A, :B ]
387
+ @ff2 = @Ff.marking :B, :A
388
+ @ff3 = @Ff.marking
389
+ end
390
+
391
+ it "should work" do
392
+ @ff1.extract_from( @sim ).must_equal [ 2, 3 ]
393
+ @ff2.extract_from( @sim ).must_equal [ 3, 2 ]
394
+ @ff3.extract_from( @sim ).must_equal [ 2, 3, 4 ]
395
+ @ff1.must_equal @Ff.marking( :A ) + @Ff.marking( :B )
396
+ end
397
+ end
398
+
399
+ describe "#Firing and #firing feature set constructors" do
400
+ before do
401
+ @ff1 = @Ff.Firing [ :A2B_t, :A_plus_t ]
402
+ @ff2 = @Ff.firing :A2B_t, :A_plus_t
403
+ @ff3 = @Ff.Firing [ :A2B, :A_plus ]
404
+ @ff4 = @Ff.firing :A2B, :A_plus
405
+ @ff5 = @Ff.firing
406
+ end
407
+
408
+ it "should work" do
409
+ @ff1.extract_from( @sim ).must_equal [ 0.42, 0.42 ]
410
+ @ff2.extract_from( @sim ).must_equal [ 0.42, 0.42 ]
411
+ @ff3.extract_from( @sim, Δt: 2 ).must_equal [ 0.04, 0.004 ]
412
+ @ff4.extract_from( @sim, Δt: 1 ).must_equal [ 0.02, 0.002 ]
413
+ @ff5.map( &:transition ).names.sort
414
+ .must_equal [ :A2B, :A_plus, :A2B_t, :A_plus_t ].sort
415
+ @ff5.extract_from( @sim, delta_time: 0.5 )
416
+ .must_equal [ 0.01, 0.001, 0.42, 0.42 ]
417
+ @ff1.must_equal @Ff.firing( :A2B_t ) + @Ff.firing( :A_plus_t )
418
+ end
419
+ end
420
+
421
+ describe "#Gradient and #gradient feature set constructors" do
422
+ before do
423
+ @ff0 = @Ff.Gradient [], transitions: []
424
+ @ff1 = @Ff.Gradient [ :A, :B ], transitions: [ :A2B ]
425
+ @ff2 = @Ff.gradient :B, :A, transitions: :A_plus
426
+ @ff3 = @Ff.gradient :C, transitions: [ :A2B, :C_plus ]
427
+ end
428
+
429
+ it "should work" do
430
+ @ff0.extract_from( @sim ).must_equal []
431
+ @ff1.extract_from( @sim ).must_equal [ -0.02, 0.02 ]
432
+ @ff2.extract_from( @sim ).must_equal [ 0.0, 0.002 ]
433
+ @ff3.extract_from( @sim )[ 0 ].must_be_within_epsilon 0.0038
434
+ @ff2.must_equal @Ff.gradient( :B, transitions: :A_plus ) +
435
+ @Ff.gradient( :A, transitions: :A_plus )
436
+ end
437
+ end
438
+
439
+ describe "#Flux and #flux feature set constructors" do
440
+ before do
441
+ @ff0 = @Ff.Flux []
442
+ @ff1 = @Ff.Flux [ :A2B ]
443
+ @ff2 = @Ff.flux :A2B, :A_plus
444
+ end
445
+
446
+ it "should work" do
447
+ @ff0.extract_from( @sim ).must_equal []
448
+ @ff1.extract_from( @sim ).must_equal [ 0.02 ]
449
+ @ff2.extract_from( @sim ).must_equal [ 0.02, 0.002 ]
450
+ @ff2.must_equal @Ff.flux( :A2B ) + @Ff.flux( :A_plus )
451
+ end
452
+ end
453
+
454
+ describe "#Delta and #delta feature set constructors" do
455
+ before do
456
+ @ff0 = @Ff.Delta [], transitions: []
457
+ @ff1 = @Ff.Delta [ :A, :B ], transitions: :A2B
458
+ @ff2 = @Ff.delta :A, :B, transitions: [ :A_plus_t, :C_minus ]
459
+ @ff3 = @Ff.delta :A, :B, transitions: :A2B
460
+ @ff4 = @Ff.delta transitions: @net.T_tt
461
+ @ff5 = @Ff.delta_timeless
462
+ @ff6 = @Ff.delta_timed
463
+ end
464
+
465
+ it "should work" do
466
+ @ff0.extract_from( @sim ).must_equal []
467
+ @ff1.extract_from( @sim, Δt: 0.1 ).must_equal [ -0.002, 0.002 ]
468
+ @ff2.extract_from( @sim ).must_equal [ 0.42, 0.0 ]
469
+ @ff3.extract_from( @sim, delta_time: 1 ).must_equal [ -0.02, 0.02 ]
470
+ @ff4.map( &:place ).names.sort.must_equal [ :A, :B, :C ].sort
471
+ @ff4.extract_from( @sim, Δt: 0.5 ).map( &[:round, 6] )
472
+ .must_equal [ -0.009, 0.01, 0.0019 ]
473
+ -> { @Ff.delta }.must_raise ArgumentError
474
+ @ff5.extract_from( @sim ).must_equal [ 0.0, 0.42, -2.0 ]
475
+ @ff6.extract_from( @sim, Δt: 0.5 ).map( &[:round, 6] )
476
+ .must_equal [ -0.009, 0.01, 0.0019 ]
477
+ @ff1.must_equal @Ff.delta( :A, transitions: :A2B ) +
478
+ @Ff.delta( :B, transitions: :A2B )
479
+ end
480
+ end
481
+
482
+ describe "#Assignment and #assignment feature set constructors" do
483
+ before do
484
+ @ff0 = @Ff.Assignment []
485
+ @ff1 = @Ff.assignment :C
486
+ @ff2 = @Ff.assignment :C, transition: :C_to_42
487
+ @ff3 = @Ff.aa
488
+ end
489
+
490
+ it "should work" do
491
+ @ff0.extract_from( @sim ).must_equal []
492
+ @ff1.extract_from( @sim ).must_equal [ 42 ]
493
+ @ff2.extract_from( @sim ).must_equal [ 42 ]
494
+ @ff3.extract_from( @sim ).must_equal [] # ends up empty because
495
+ # techically, place :C with its A transition :C_to_42 does not
496
+ # make sense, as there are also a transitions upstream of :C.
497
+ -> { @Ff.assignment }.must_raise ArgumentError
498
+ @ff1.must_equal @ff2
499
+ end
500
+ end
501
+
502
+ describe "#[] constructor" do
503
+ before do
504
+ @ff0 = @Ff[]
505
+ @ff1 = @Ff[ :A, :A2B, :A2B_t ]
506
+ @ff2 = @Ff[ marking: [ :A, :B ],
507
+ flux: :A2B,
508
+ gradient: [ :A, transitions: :A2B ] ]
509
+ end
510
+
511
+ it "should work" do
512
+ @ff0.extract_from( @sim ).must_equal []
513
+ @ff1.extract_from( @sim ).must_equal [ 2, 0.02, 0.42 ]
514
+ @ff2.extract_from( @sim ).must_equal [ 2, 3, 0.02, -0.02 ]
515
+ -> { @Ff[ :A, marking: [ :B ] ] }.must_raise ArgumentError
516
+ @ff2.must_equal @Ff[ :A, :B, :A2B ] +
517
+ @Ff.gradient( :A, transitions: :A2B )
518
+ end
519
+ end
520
+
521
+ describe "feature reduction methods and other miscellanea" do
522
+ before do
523
+ @ff = @Ff[ marking: [ :A, :B ], flux: :A2B,
524
+ gradient: [ :A, transitions: :A2B ] ]
525
+ @ff2 = @Ff[ :A2B, :A_plus ]
526
+ end
527
+
528
+ it "should work" do
529
+ ( @ff + @ff2 ).labels
530
+ .must_equal [ ":A", ":B", "Φ:A2B", "∂:A:A2B", "Φ:A2B", "Φ:A_plus" ]
531
+ @ff.Marking( [ :A ] ).must_equal @Ff[ :A ]
532
+ @ff.marking.must_equal @Ff[ :A, :B ]
533
+ @ff.Firing( [ ] ).must_equal @Ff[]
534
+ @ff.firing.must_equal @Ff[]
535
+ @ff.flux( :A2B ).must_equal @Ff[ :A2B ]
536
+ -> { @ff.Flux( [ :A ] ) }.must_raise NameError
537
+ @ff.gradient( :A, transitions: :A2B )
538
+ .must_equal @Ff.gradient( :A, transitions: :A2B )
539
+ @ff.delta.must_equal @Ff[]
540
+ @ff.assignment.must_equal @Ff[]
541
+ end
542
+ end
211
543
  end
212
544
 
213
- it "should be constructible" do
214
- ds = @net.State.marking( [:A, :B] ).new_dataset( type: :foobar )
215
- ds.update foo: [ 42, 43 ]
216
- ds.update bar: [ 43, 42 ]
217
- ds.timed?.must_equal false
218
- ds2 = @net.State.marking.new_dataset( type: :timed )
219
- ds2.timed?.must_equal true
220
- ds2.features.must_equal @net.State.marking( [:A, :B] )
545
+ describe YPetri::Net::State::Features::Record do
546
+ before do
547
+ @sim = @net.simulation step: 1.0
548
+ @Ff = @sim.net.State.Features
549
+ @ff = @Ff[ :A, :B, :A2B ] + @Ff.assignment( :C )
550
+ @ff2 = @Ff.marking + @Ff[ :A2B ]
551
+ end
552
+
553
+ describe "instance methods" do
554
+ before do
555
+ @tuple = @ff.extract_from( @sim )
556
+ @tuple2 = @ff2.extract_from( @sim )
557
+ @r = @ff.Record.load @tuple
558
+ @r2 = @ff2.Record.load @tuple2
559
+ end
560
+
561
+ it "should work" do
562
+ @r.must_equal [ 2, 3, 0.02, 42 ]
563
+ @r.fetch( :A ).must_equal 2
564
+ @r.fetch( :A2B ).must_equal 0.02
565
+ @r.fetch( @Ff[ assignment: :C ].first ).must_equal 42
566
+ @r.dump.class.must_equal Array
567
+ @r.dump.must_equal [ 2, 3, 0.02, 42 ]
568
+ @r.dump( precision: 1 ).must_equal [ 2, 3, 0, 42 ]
569
+ @r2.state.must_equal [ 2, 3, 4 ]
570
+ @r2.reconstruct( marking_clamps: { B: 43 }, step: 0.1, time: 0..100 )
571
+ .must_be_kind_of @net.Simulation
572
+ @r2.Marking( [ :C, :A ] ).must_equal [ 4, 2 ]
573
+ @r2.marking( :B ).must_equal [ 3 ]
574
+ @r2.flux.must_equal [ 0.02 ]
575
+ @r2.firing.must_equal []
576
+ @r2.gradient.must_equal []
577
+ @r2.delta.must_equal []
578
+ @r.features.map( &:type )
579
+ .must_equal [ :marking, :marking, :flux, :assignment ]
580
+ @r.assignment.must_equal [ 42 ]
581
+ u = @ff.Record [ 0, 0, 0 ]
582
+ u.must_equal @ff.Record( [ 0, 0, 0 ] )
583
+ v = @ff.load [ 0, 3, 4 ]
584
+ u.euclidean_distance( v ).must_be_within_epsilon 5
585
+ end
586
+ end
221
587
  end
222
588
 
223
- describe "timed dataset" do
589
+ describe YPetri::Net::State do
224
590
  before do
225
- @ds = @net.State.marking.new_dataset( type: :timed )
226
- @ds.update 0.0 => [ 0, 0 ]
227
- @ds.update 10.0 => [ 1, 0.5 ]
228
- @ds.update 50.0 => [ 2, 3 ]
229
- @ds.update 200.0 => [ 2.5, 7 ]
591
+ @sim = @net.simulation step: 1.0
592
+ @S = @net.State
230
593
  end
231
594
 
232
- it "should give a nice plot" do
233
- @ds.plot
595
+ it "should have certain feature constructors" do
596
+ @S.Features( [ :A, :B, :A2B ] ).must_equal @S.Features[ @S.Feature( :A ),
597
+ @S.Feature( :B ),
598
+ @S.Feature( :A2B ) ]
234
599
  end
235
600
 
236
- describe "resampling" do
601
+ describe "instance methods" do
602
+ before do
603
+ @ff = @S.Features[ :A, :B, :C, :A2B ]
604
+ @r = @ff.load @ff.extract_from( @sim )
605
+ @s = @r.state
606
+ end
607
+
608
+ it "should have certain instance methods" do
609
+ @s.marking( :A ).must_equal @r.fetch( :A )
610
+ @s.markings( :A, :B ).must_equal @r.marking( :A, :B )
611
+ end
612
+ end
613
+ end
614
+
615
+ describe YPetri::Net::DataSet do
616
+ it "should be constructible" do
617
+ ds = @net.State.Features.Marking( [ :A, :B ] ).DataSet.new( type: :foobar )
618
+ ds.update foo: [ 42, 43 ] # add line 1
619
+ ds.update bar: [ 43, 44 ] # add line 2
620
+ ds.timed?.must_equal false
621
+ ds2 = @net.State.Features.marking.DataSet.new( type: :timed )
622
+ ds2.features.must_equal @net.State.Features.marking( :A, :B, :C )
623
+ end
624
+
625
+ describe "timed dataset" do
237
626
  before do
238
- @resampled_ds = @ds.resample sampling: 11
627
+ @ds = @net.State.Features.marking( :A, :B ).DataSet.new( type: :timed )
628
+ @ds.update 0.0 => [ 0, 0 ]
629
+ @ds.update 10.0 => [ 1, 0.5 ]
630
+ @ds.update 50.0 => [ 2, 3 ]
631
+ @ds.update 200.0 => [ 2.5, 7 ]
239
632
  end
240
633
 
241
634
  it "should give a nice plot" do
242
- @resampled_ds.plot
635
+ @ds.plot
243
636
  end
244
637
 
245
- it "should be able to reconstruct the flux" do
246
- @resampled_ds.flux.plot
638
+ describe "resampling" do
639
+ before do
640
+ @resampled_ds = @ds.resample sampling: 11
641
+ end
642
+
643
+ it "should give a nice plot" do
644
+ @resampled_ds.plot
645
+ end
646
+
647
+ it "should be able to reconstruct flux" do
648
+ @resampled_ds.flux.plot
649
+ end
247
650
  end
248
651
  end
249
652
  end
data/test/place_test.rb CHANGED
@@ -1,6 +1,7 @@
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'
@@ -15,22 +16,22 @@ describe YPetri::Place do
15
16
  name: "P1"
16
17
  p.namespace.must_equal YPetri::Place
17
18
  p.name.must_equal :P1
18
- p.inspect[0..7].must_equal "#<Place:"
19
- p.to_s[0..2].must_equal 'P1['
19
+ p.inspect[0..7].must_equal "P1"
20
+ p.to_s[0..1].must_equal 'P1'
20
21
  p.marking.must_equal 1.1 # Attention, #marking overloaded with guard setup!
21
22
  p.quantum.must_equal 0.1
22
23
  p.add 1
23
24
  p.value.must_equal 2.1 # near-alias of #marking (no guard setup)
24
25
  p.subtract 0.5
25
- p.m.must_equal 1.6 # alias of #value
26
+ p.marking.must_equal 1.6 # alias of #value
26
27
  p.reset_marking
27
28
  p.marking.must_equal 3.2
28
29
  p.marking = 42
29
- p.m.must_equal 42
30
- p.m = 43
31
- p.m.must_equal 43
30
+ p.marking.must_equal 42
31
+ p.marking = 43
32
+ p.marking.must_equal 43
32
33
  p.value = 44
33
- p.m.must_equal 44
34
+ p.marking.must_equal 44
34
35
  p.upstream_arcs.must_equal []
35
36
  p.upstream_transitions.must_equal [] # alias of #upstream_arcs
36
37
  p.ϝ.must_equal [] # alias of #upstream_arcs
@@ -41,6 +42,9 @@ describe YPetri::Place do
41
42
  p.upstream_places.must_equal [] # alias for #precedents
42
43
  p.dependents.must_equal []
43
44
  p.downstream_places.must_equal [] # alias for #dependents
45
+ p.upstream_net.places.must_equal []
46
+ p.downstream_net.places.must_equal []
47
+ p.local_net.places.must_equal []
44
48
  # fire methods
45
49
  assert_respond_to p, :fire_upstream
46
50
  assert_respond_to p, :fire_upstream!