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.
- checksums.yaml +4 -4
- data/LICENSE.txt +675 -0
- data/README.md +6 -3
- data/Rakefile +1 -1
- data/lib/y_petri/agent/{petri_net_related.rb → petri_net_aspect.rb} +34 -10
- data/lib/y_petri/agent/{simulation_related.rb → simulation_aspect.rb} +49 -34
- data/lib/y_petri/agent.rb +5 -5
- data/lib/y_petri/core/guarded.rb +24 -0
- data/lib/y_petri/core/timed/euler.rb +4 -8
- data/lib/y_petri/core/timed/gillespie.rb +11 -17
- data/lib/y_petri/core/timed/methods.rb +23 -0
- data/lib/y_petri/core/timed/pseudo_euler.rb +10 -13
- data/lib/y_petri/core/timed/quasi_euler.rb +9 -8
- data/lib/y_petri/core/timed/runge_kutta.rb +10 -18
- data/lib/y_petri/core/timed.rb +6 -14
- data/lib/y_petri/core/timeless/methods.rb +15 -0
- data/lib/y_petri/core/timeless/pseudo_euler.rb +4 -8
- data/lib/y_petri/core/timeless.rb +9 -4
- data/lib/y_petri/core.rb +44 -42
- data/lib/y_petri/net/data_set.rb +246 -142
- data/lib/y_petri/net/node_access.rb +282 -0
- data/lib/y_petri/net/own_state.rb +14 -4
- data/lib/y_petri/net/state/feature/assignment.rb +123 -0
- data/lib/y_petri/net/state/feature/delta.rb +55 -35
- data/lib/y_petri/net/state/feature/firing.rb +68 -25
- data/lib/y_petri/net/state/feature/flux.rb +9 -2
- data/lib/y_petri/net/state/feature/gradient.rb +36 -19
- data/lib/y_petri/net/state/feature/marking.rb +10 -5
- data/lib/y_petri/net/state/feature.rb +105 -11
- data/lib/y_petri/net/state/features/record.rb +144 -99
- data/lib/y_petri/net/state/features.rb +327 -200
- data/lib/y_petri/net/state.rb +48 -82
- data/lib/y_petri/net/visualization.rb +1 -1
- data/lib/y_petri/net.rb +62 -47
- data/lib/y_petri/place/arcs.rb +44 -0
- data/lib/y_petri/place/features.rb +115 -0
- data/lib/y_petri/place.rb +62 -29
- data/lib/y_petri/simulation/dependency.rb +31 -67
- data/lib/y_petri/simulation/feature_set.rb +1 -1
- data/lib/y_petri/simulation/initial_marking/access.rb +42 -26
- data/lib/y_petri/simulation/marking_clamps/access.rb +22 -17
- data/lib/y_petri/simulation/marking_clamps.rb +0 -2
- data/lib/y_petri/simulation/marking_vector/access.rb +102 -40
- data/lib/y_petri/simulation/marking_vector.rb +35 -37
- data/lib/y_petri/simulation/matrix.rb +1 -1
- data/lib/y_petri/simulation/node_representation.rb +25 -0
- data/lib/y_petri/simulation/nodes/access.rb +78 -0
- data/lib/y_petri/simulation/{elements.rb → nodes.rb} +14 -13
- data/lib/y_petri/simulation/place_mapping.rb +2 -2
- data/lib/y_petri/simulation/place_representation.rb +8 -7
- data/lib/y_petri/simulation/places/access.rb +89 -70
- data/lib/y_petri/simulation/places/free.rb +1 -1
- data/lib/y_petri/simulation/places/types.rb +20 -22
- data/lib/y_petri/simulation/places.rb +23 -18
- data/lib/y_petri/simulation/recorder.rb +23 -18
- data/lib/y_petri/simulation/timed/recorder.rb +19 -11
- data/lib/y_petri/simulation/timed.rb +93 -29
- data/lib/y_petri/simulation/timeless/recorder.rb +11 -6
- data/lib/y_petri/simulation/timeless.rb +13 -3
- data/lib/y_petri/simulation/transition_representation/A.rb +24 -4
- data/lib/y_petri/simulation/transition_representation/S.rb +11 -1
- data/lib/y_petri/simulation/transition_representation/T.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/Ts.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/a.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/s.rb +12 -1
- data/lib/y_petri/simulation/transition_representation/t.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/tS.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/ts.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/types.rb +1 -1
- data/lib/y_petri/simulation/transition_representation.rb +4 -11
- data/lib/y_petri/simulation/transitions/A.rb +17 -2
- data/lib/y_petri/simulation/transitions/S.rb +1 -1
- data/lib/y_petri/simulation/transitions/T.rb +1 -1
- data/lib/y_petri/simulation/transitions/Ts.rb +6 -5
- data/lib/y_petri/simulation/transitions/a.rb +1 -1
- data/lib/y_petri/simulation/transitions/access.rb +195 -168
- data/lib/y_petri/simulation/transitions/s.rb +1 -1
- data/lib/y_petri/simulation/transitions/t.rb +1 -1
- data/lib/y_petri/simulation/transitions/tS.rb +1 -1
- data/lib/y_petri/simulation/transitions/ts.rb +1 -1
- data/lib/y_petri/simulation/transitions/types.rb +1 -1
- data/lib/y_petri/simulation/transitions.rb +5 -7
- data/lib/y_petri/simulation.rb +84 -90
- data/lib/y_petri/transition/A.rb +8 -2
- data/lib/y_petri/transition/T.rb +25 -2
- data/lib/y_petri/transition/arcs.rb +19 -3
- data/lib/y_petri/transition/construction_convenience.rb +11 -10
- data/lib/y_petri/transition/t.rb +14 -1
- data/lib/y_petri/transition/types.rb +6 -1
- data/lib/y_petri/transition.rb +9 -12
- data/lib/y_petri/version.rb +1 -1
- data/lib/y_petri/world/dependency.rb +3 -3
- data/lib/y_petri/world/{petri_net_related.rb → petri_net_aspect.rb} +4 -4
- data/lib/y_petri/world/simulation_aspect.rb +352 -0
- data/lib/y_petri/world.rb +4 -4
- data/lib/y_petri.rb +1 -1
- data/test/agent_test.rb +2 -1
- data/test/examples/demonstrator.rb +4 -1
- data/test/examples/demonstrator_2.rb +5 -0
- data/test/examples/demonstrator_4.rb +6 -5
- data/test/examples/example_2.rb +2 -0
- data/test/examples/manual_examples.rb +4 -4
- data/test/net_test.rb +457 -54
- data/test/place_test.rb +11 -7
- data/test/simulation_test.rb +358 -331
- data/test/transition_test.rb +11 -10
- data/test/world_test.rb +2 -0
- data/test/y_petri_test.rb +2 -1
- data/y_petri.gemspec +24 -18
- metadata +71 -17
- data/LICENSE +0 -22
- data/lib/y_petri/net/element_access.rb +0 -239
- data/lib/y_petri/simulation/element_representation.rb +0 -20
- data/lib/y_petri/simulation/elements/access.rb +0 -57
- data/lib/y_petri/transition/type.rb +0 -103
- data/lib/y_petri/transition/type_information.rb +0 -103
- 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.
|
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.
|
35
|
-
@net.places(
|
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
|
-
|
54
|
-
|
55
|
-
|
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 )
|
74
|
+
assert @net.include?( @p1 )
|
75
|
+
assert ! @net.include?( YPetri::Place.send :new )
|
74
76
|
end
|
75
77
|
|
76
|
-
it "should know its state
|
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.
|
101
|
-
@net.transitions(
|
102
|
-
@net.
|
103
|
-
@net.
|
104
|
-
@net.
|
105
|
-
@net.
|
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( :
|
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
|
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
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
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
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
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
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
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
|
589
|
+
describe YPetri::Net::State do
|
224
590
|
before do
|
225
|
-
@
|
226
|
-
@
|
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
|
233
|
-
@
|
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 "
|
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
|
-
@
|
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
|
-
@
|
635
|
+
@ds.plot
|
243
636
|
end
|
244
637
|
|
245
|
-
|
246
|
-
|
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 "
|
19
|
-
p.to_s[0..
|
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.
|
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.
|
30
|
-
p.
|
31
|
-
p.
|
30
|
+
p.marking.must_equal 42
|
31
|
+
p.marking = 43
|
32
|
+
p.marking.must_equal 43
|
32
33
|
p.value = 44
|
33
|
-
p.
|
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!
|