y_petri 2.2.4 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +675 -0
  3. data/README.md +6 -3
  4. data/Rakefile +1 -1
  5. data/lib/y_petri/agent/{petri_net_related.rb → petri_net_aspect.rb} +34 -10
  6. data/lib/y_petri/agent/{simulation_related.rb → simulation_aspect.rb} +49 -34
  7. data/lib/y_petri/agent.rb +5 -5
  8. data/lib/y_petri/core/guarded.rb +24 -0
  9. data/lib/y_petri/core/timed/euler.rb +4 -8
  10. data/lib/y_petri/core/timed/gillespie.rb +11 -17
  11. data/lib/y_petri/core/timed/methods.rb +23 -0
  12. data/lib/y_petri/core/timed/pseudo_euler.rb +10 -13
  13. data/lib/y_petri/core/timed/quasi_euler.rb +9 -8
  14. data/lib/y_petri/core/timed/runge_kutta.rb +10 -18
  15. data/lib/y_petri/core/timed.rb +6 -14
  16. data/lib/y_petri/core/timeless/methods.rb +15 -0
  17. data/lib/y_petri/core/timeless/pseudo_euler.rb +4 -8
  18. data/lib/y_petri/core/timeless.rb +9 -4
  19. data/lib/y_petri/core.rb +44 -42
  20. data/lib/y_petri/net/data_set.rb +246 -142
  21. data/lib/y_petri/net/node_access.rb +282 -0
  22. data/lib/y_petri/net/own_state.rb +14 -4
  23. data/lib/y_petri/net/state/feature/assignment.rb +123 -0
  24. data/lib/y_petri/net/state/feature/delta.rb +55 -35
  25. data/lib/y_petri/net/state/feature/firing.rb +68 -25
  26. data/lib/y_petri/net/state/feature/flux.rb +9 -2
  27. data/lib/y_petri/net/state/feature/gradient.rb +36 -19
  28. data/lib/y_petri/net/state/feature/marking.rb +10 -5
  29. data/lib/y_petri/net/state/feature.rb +105 -11
  30. data/lib/y_petri/net/state/features/record.rb +144 -99
  31. data/lib/y_petri/net/state/features.rb +327 -200
  32. data/lib/y_petri/net/state.rb +48 -82
  33. data/lib/y_petri/net/visualization.rb +1 -1
  34. data/lib/y_petri/net.rb +62 -47
  35. data/lib/y_petri/place/arcs.rb +44 -0
  36. data/lib/y_petri/place/features.rb +115 -0
  37. data/lib/y_petri/place.rb +62 -29
  38. data/lib/y_petri/simulation/dependency.rb +31 -67
  39. data/lib/y_petri/simulation/feature_set.rb +1 -1
  40. data/lib/y_petri/simulation/initial_marking/access.rb +42 -26
  41. data/lib/y_petri/simulation/marking_clamps/access.rb +22 -17
  42. data/lib/y_petri/simulation/marking_clamps.rb +0 -2
  43. data/lib/y_petri/simulation/marking_vector/access.rb +102 -40
  44. data/lib/y_petri/simulation/marking_vector.rb +35 -37
  45. data/lib/y_petri/simulation/matrix.rb +1 -1
  46. data/lib/y_petri/simulation/node_representation.rb +25 -0
  47. data/lib/y_petri/simulation/nodes/access.rb +78 -0
  48. data/lib/y_petri/simulation/{elements.rb → nodes.rb} +14 -13
  49. data/lib/y_petri/simulation/place_mapping.rb +2 -2
  50. data/lib/y_petri/simulation/place_representation.rb +8 -7
  51. data/lib/y_petri/simulation/places/access.rb +89 -70
  52. data/lib/y_petri/simulation/places/free.rb +1 -1
  53. data/lib/y_petri/simulation/places/types.rb +20 -22
  54. data/lib/y_petri/simulation/places.rb +23 -18
  55. data/lib/y_petri/simulation/recorder.rb +23 -18
  56. data/lib/y_petri/simulation/timed/recorder.rb +19 -11
  57. data/lib/y_petri/simulation/timed.rb +93 -29
  58. data/lib/y_petri/simulation/timeless/recorder.rb +11 -6
  59. data/lib/y_petri/simulation/timeless.rb +13 -3
  60. data/lib/y_petri/simulation/transition_representation/A.rb +24 -4
  61. data/lib/y_petri/simulation/transition_representation/S.rb +11 -1
  62. data/lib/y_petri/simulation/transition_representation/T.rb +1 -1
  63. data/lib/y_petri/simulation/transition_representation/Ts.rb +1 -1
  64. data/lib/y_petri/simulation/transition_representation/a.rb +1 -1
  65. data/lib/y_petri/simulation/transition_representation/s.rb +12 -1
  66. data/lib/y_petri/simulation/transition_representation/t.rb +1 -1
  67. data/lib/y_petri/simulation/transition_representation/tS.rb +1 -1
  68. data/lib/y_petri/simulation/transition_representation/ts.rb +1 -1
  69. data/lib/y_petri/simulation/transition_representation/types.rb +1 -1
  70. data/lib/y_petri/simulation/transition_representation.rb +4 -11
  71. data/lib/y_petri/simulation/transitions/A.rb +17 -2
  72. data/lib/y_petri/simulation/transitions/S.rb +1 -1
  73. data/lib/y_petri/simulation/transitions/T.rb +1 -1
  74. data/lib/y_petri/simulation/transitions/Ts.rb +6 -5
  75. data/lib/y_petri/simulation/transitions/a.rb +1 -1
  76. data/lib/y_petri/simulation/transitions/access.rb +195 -168
  77. data/lib/y_petri/simulation/transitions/s.rb +1 -1
  78. data/lib/y_petri/simulation/transitions/t.rb +1 -1
  79. data/lib/y_petri/simulation/transitions/tS.rb +1 -1
  80. data/lib/y_petri/simulation/transitions/ts.rb +1 -1
  81. data/lib/y_petri/simulation/transitions/types.rb +1 -1
  82. data/lib/y_petri/simulation/transitions.rb +5 -7
  83. data/lib/y_petri/simulation.rb +84 -90
  84. data/lib/y_petri/transition/A.rb +8 -2
  85. data/lib/y_petri/transition/T.rb +25 -2
  86. data/lib/y_petri/transition/arcs.rb +19 -3
  87. data/lib/y_petri/transition/construction_convenience.rb +11 -10
  88. data/lib/y_petri/transition/t.rb +14 -1
  89. data/lib/y_petri/transition/types.rb +6 -1
  90. data/lib/y_petri/transition.rb +9 -12
  91. data/lib/y_petri/version.rb +1 -1
  92. data/lib/y_petri/world/dependency.rb +3 -3
  93. data/lib/y_petri/world/{petri_net_related.rb → petri_net_aspect.rb} +4 -4
  94. data/lib/y_petri/world/simulation_aspect.rb +352 -0
  95. data/lib/y_petri/world.rb +4 -4
  96. data/lib/y_petri.rb +1 -1
  97. data/test/agent_test.rb +2 -1
  98. data/test/examples/demonstrator.rb +4 -1
  99. data/test/examples/demonstrator_2.rb +5 -0
  100. data/test/examples/demonstrator_4.rb +6 -5
  101. data/test/examples/example_2.rb +2 -0
  102. data/test/examples/manual_examples.rb +4 -4
  103. data/test/net_test.rb +457 -54
  104. data/test/place_test.rb +11 -7
  105. data/test/simulation_test.rb +358 -331
  106. data/test/transition_test.rb +11 -10
  107. data/test/world_test.rb +2 -0
  108. data/test/y_petri_test.rb +2 -1
  109. data/y_petri.gemspec +24 -18
  110. metadata +71 -17
  111. data/LICENSE +0 -22
  112. data/lib/y_petri/net/element_access.rb +0 -239
  113. data/lib/y_petri/simulation/element_representation.rb +0 -20
  114. data/lib/y_petri/simulation/elements/access.rb +0 -57
  115. data/lib/y_petri/transition/type.rb +0 -103
  116. data/lib/y_petri/transition/type_information.rb +0 -103
  117. data/lib/y_petri/world/simulation_related.rb +0 -176
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!