y_petri 2.3.12 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/y_petri/core/timed/runge_kutta.rb +103 -49
- data/lib/y_petri/core/timed.rb +26 -8
- data/lib/y_petri/core/timeless.rb +8 -0
- data/lib/y_petri/core.rb +50 -40
- data/lib/y_petri/simulation/dependency.rb +8 -8
- data/lib/y_petri/simulation/marking_vector.rb +20 -6
- data/lib/y_petri/simulation/matrix.rb +11 -1
- data/lib/y_petri/simulation/nodes/access.rb +1 -1
- data/lib/y_petri/simulation/nodes.rb +5 -5
- data/lib/y_petri/simulation/place_mapping.rb +2 -2
- data/lib/y_petri/simulation/places/access.rb +10 -9
- data/lib/y_petri/simulation/places/types.rb +8 -5
- data/lib/y_petri/simulation/places.rb +1 -3
- data/lib/y_petri/simulation/recorder.rb +23 -0
- data/lib/y_petri/simulation/timed.rb +104 -11
- data/lib/y_petri/simulation/transition_representation/types.rb +4 -12
- data/lib/y_petri/simulation/transitions/access.rb +6 -6
- data/lib/y_petri/simulation/transitions/types.rb +20 -30
- data/lib/y_petri/simulation/transitions.rb +3 -1
- data/lib/y_petri/simulation.rb +17 -14
- data/lib/y_petri/version.rb +1 -1
- data/lib/y_petri/world.rb +1 -1
- data/test/simulation_test.rb +211 -50
- metadata +2 -2
data/test/simulation_test.rb
CHANGED
@@ -321,61 +321,222 @@ require_relative '../lib/y_petri' # tested component itself
|
|
321
321
|
# end
|
322
322
|
# end
|
323
323
|
|
324
|
-
describe "timed simulation" do
|
324
|
+
# describe "timed simulation" do
|
325
|
+
# before do
|
326
|
+
# self.class.class_exec { include YPetri }
|
327
|
+
# A = Place m!: 0.5
|
328
|
+
# B = Place m!: 0.5
|
329
|
+
# A_pump = TT s: { A: -1 } do 0.005 end
|
330
|
+
# B_decay = Transition s: { B: -1 }, rate: 0.05
|
331
|
+
# run!
|
332
|
+
# end
|
333
|
+
|
334
|
+
# it "should work with the default method" do
|
335
|
+
# places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected
|
336
|
+
# s = simulation
|
337
|
+
# s.settings.must_equal( { method: :basic, 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
|
380
|
+
# end
|
381
|
+
# end
|
382
|
+
|
383
|
+
describe "timed simulation with other methods" do
|
384
|
+
before do
|
385
|
+
self.class.class_exec { include YPetri }
|
386
|
+
A = Place m!: 0.5 unless places.names.include? :A
|
387
|
+
B = Place m!: 0.5 unless places.names.include? :B
|
388
|
+
A_pump = TT s: { A: -1 } do 0.005 end unless transitions.names.include? :A_pump
|
389
|
+
B_decay = Transition s: { B: -1 }, rate: 0.05 unless transitions.names.include? :B_decay
|
390
|
+
end
|
391
|
+
|
392
|
+
# it "should work with the default method" do
|
393
|
+
# basic_simulation = new_simulation
|
394
|
+
# s = basic_simulation
|
395
|
+
# s.run!
|
396
|
+
# places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected
|
397
|
+
# s.settings.must_equal( { method: :basic, guarded: false,
|
398
|
+
# step: 0.1, sampling: 5, time: 0..60 } )
|
399
|
+
# assert s.recording.to_csv.start_with?( ":event,:A,:B\n" +
|
400
|
+
# "0.0,0.5,0.5\n" +
|
401
|
+
# "5.0,0.475,0.38916\n" +
|
402
|
+
# "10.0,0.45,0.30289\n" +
|
403
|
+
# "15.0,0.425,0.23574\n" +
|
404
|
+
# "20.0,0.4,0.18348\n" +
|
405
|
+
# "25.0,0.375,0.1428\n" )
|
406
|
+
# assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" )
|
407
|
+
# s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0,
|
408
|
+
# 25.0, 30.0, 35.0, 40.0, 45.0,
|
409
|
+
# 50.0, 55.0, 60.0 ]
|
410
|
+
# s.recording.values_at( 5, 10 )
|
411
|
+
# .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ]
|
412
|
+
# s.recording.slice( 2..12 )
|
413
|
+
# .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } )
|
414
|
+
# s.recording.net
|
415
|
+
# .must_equal net
|
416
|
+
# s.recording.features
|
417
|
+
# .must_equal net.State.Features.marking( :A, :B )
|
418
|
+
# net.State.Features.State
|
419
|
+
# .must_equal net.State
|
420
|
+
# s.recording.net.State
|
421
|
+
# .must_equal net.State
|
422
|
+
# s.recording.series( marking: [:A] )
|
423
|
+
# .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325,
|
424
|
+
# 0.3, 0.275, 0.25, 0.225, 0.2 ] ]
|
425
|
+
# s.net.State.Features.firing.map( &:transition ).names
|
426
|
+
# .must_equal [ :A_pump, :B_decay ]
|
427
|
+
# s.recording.reduce_features( s.net.State.Features.firing, Δt: 1 )
|
428
|
+
# .to_h.take( 2 ).map( &:flatten! ).map { |a| a.map &[:round, 6 ] }
|
429
|
+
# .must_equal [ [ 0.0, 0.005, 0.025 ], [ 5.0, 0.005, 0.019458 ] ]
|
430
|
+
# s.recording.firing( Δt: 0.1 ).series.map( &:first ).map( &[ :round, 6 ] )
|
431
|
+
# .must_equal [ 0.0005, 0.0025 ]
|
432
|
+
# s.recording.Firing( [] )
|
433
|
+
# .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 )
|
434
|
+
# s.recording
|
435
|
+
# .delta( :A, transitions: [:A_pump], delta_time: 0.1 )
|
436
|
+
# .series
|
437
|
+
# .must_equal [ [ -0.0005 ] * 13 ]
|
438
|
+
# plot_state
|
439
|
+
# sleep 5
|
440
|
+
# end
|
441
|
+
|
442
|
+
# it "should work with :runge_kutta method" do
|
443
|
+
# rk_simulation = new_simulation( method: :runge_kutta )
|
444
|
+
# s = rk_simulation
|
445
|
+
# s.run!
|
446
|
+
# places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected
|
447
|
+
# s.settings.must_equal( { method: :runge_kutta, guarded: false,
|
448
|
+
# step: 0.1, sampling: 5, time: 0..60 } )
|
449
|
+
# assert s.recording.to_csv.start_with?( ":event,:A,:B\n" +
|
450
|
+
# "0.0,0.5,0.5\n" +
|
451
|
+
# "5.0,0.475,0.38916\n" +
|
452
|
+
# "10.0,0.45,0.30289\n" +
|
453
|
+
# "15.0,0.425,0.23574\n" +
|
454
|
+
# "20.0,0.4,0.18348\n" +
|
455
|
+
# "25.0,0.375,0.1428\n" )
|
456
|
+
# assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" )
|
457
|
+
# s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0,
|
458
|
+
# 25.0, 30.0, 35.0, 40.0, 45.0,
|
459
|
+
# 50.0, 55.0, 60.0 ]
|
460
|
+
# s.recording.values_at( 5, 10 )
|
461
|
+
# .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ]
|
462
|
+
# s.recording.slice( 2..12 )
|
463
|
+
# .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } )
|
464
|
+
# s.recording.net
|
465
|
+
# .must_equal net
|
466
|
+
# s.recording.features
|
467
|
+
# .must_equal net.State.Features.marking( :A, :B )
|
468
|
+
# net.State.Features.State
|
469
|
+
# .must_equal net.State
|
470
|
+
# s.recording.net.State
|
471
|
+
# .must_equal net.State
|
472
|
+
# s.recording.series( marking: [:A] )
|
473
|
+
# .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325,
|
474
|
+
# 0.3, 0.275, 0.25, 0.225, 0.2 ] ]
|
475
|
+
# s.net.State.Features.firing.map( &:transition ).names
|
476
|
+
# .must_equal [ :A_pump, :B_decay ]
|
477
|
+
# s.recording.reduce_features( s.net.State.Features.firing, Δt: 1 )
|
478
|
+
# .to_h.take( 2 ).map( &:flatten! ).map { |a| a.map &[:round, 6 ] }
|
479
|
+
# .must_equal [ [ 0.0, 0.005, 0.025 ], [ 5.0, 0.005, 0.019458 ] ]
|
480
|
+
# s.recording.firing( Δt: 0.1 ).series.map( &:first ).map( &[ :round, 6 ] )
|
481
|
+
# .must_equal [ 0.0005, 0.0025 ]
|
482
|
+
# s.recording.Firing( [] )
|
483
|
+
# .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 )
|
484
|
+
# s.recording
|
485
|
+
# .delta( :A, transitions: [:A_pump], delta_time: 0.1 )
|
486
|
+
# .series
|
487
|
+
# .must_equal [ [ -0.0005 ] * 13 ]
|
488
|
+
# plot_state
|
489
|
+
# sleep 5
|
490
|
+
# end
|
491
|
+
end
|
492
|
+
|
493
|
+
describe "timed simulation with other methods" do
|
325
494
|
before do
|
326
495
|
self.class.class_exec { include YPetri }
|
327
|
-
A = Place m!: 0.5
|
328
|
-
B = Place m!: 0.5
|
329
|
-
A_pump = TT s: { A: -1 } do 0.005 end
|
330
|
-
B_decay = Transition s: { B: -1 }, rate: 0.05
|
331
|
-
run!
|
496
|
+
A = Place m!: 0.5 unless places.names.include? :A
|
497
|
+
B = Place m!: 0.5 unless places.names.include? :B
|
498
|
+
A_pump = TT s: { A: -1 } do 0.005 end unless transitions.names.include? :A_pump
|
499
|
+
B_decay = Transition s: { B: -1 }, rate: 0.05 unless transitions.names.include? :B_decay
|
332
500
|
end
|
333
501
|
|
334
|
-
it "should
|
335
|
-
|
336
|
-
s =
|
337
|
-
s.
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
s.
|
353
|
-
|
354
|
-
s.
|
355
|
-
|
356
|
-
s.
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
s.
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
s.
|
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 ]
|
502
|
+
it "should work with :runge_kutta method" do
|
503
|
+
rk_simulation = new_simulation( method: :runge_kutta )
|
504
|
+
s = rk_simulation
|
505
|
+
s.state.to_a.must_equal [ 0.5, 0.5 ]
|
506
|
+
c = s.rk_core
|
507
|
+
c.must_be_kind_of YPetri::Core::Timed
|
508
|
+
c.marking_of_free_places.annotation.names.must_equal c.free_pp.names
|
509
|
+
c.marking_of_clamped_places.annotation.names.must_equal c.clamped_pp.names
|
510
|
+
c.simulation_method.must_equal :runge_kutta
|
511
|
+
c.marking_of_free_places.reset! [ 1.5, 1.5 ]
|
512
|
+
c.reset_time! 1.5
|
513
|
+
c.time.must_equal 1.5
|
514
|
+
c.state.to_a.must_equal [ 1.5, 1.5 ]
|
515
|
+
x = []
|
516
|
+
c.set_user_alert_closure do |mv| x << mv.to_a; x.flatten end
|
517
|
+
c.step! 2.0
|
518
|
+
c.time.must_equal 3.5
|
519
|
+
c.state.to_a.must_equal [ 1.49, 1.35725625 ]
|
520
|
+
s.time.must_equal 0.0
|
521
|
+
s.step.must_equal 0.1
|
522
|
+
s.step!
|
523
|
+
s.state.to_a[ 0 ].must_equal 0.4995
|
524
|
+
s.state.to_a[ 1 ].must_be_within_epsilon 0.49750624
|
525
|
+
s.time.must_equal 0.1
|
526
|
+
s.step = 5.0
|
527
|
+
s.run!
|
528
|
+
s.time.must_equal 60.0
|
529
|
+
puts
|
530
|
+
puts "by Runge-Kutta method (step #{s.step}):"
|
531
|
+
p s.state.to_h
|
532
|
+
s.state.to_a[ 0 ].must_be_within_epsilon 0.2
|
533
|
+
s.state.to_a[ 1 ].must_be_within_epsilon 0.024893534
|
378
534
|
plot_state
|
535
|
+
s = new_simulation
|
536
|
+
s.run!
|
537
|
+
puts
|
538
|
+
puts "by Euler method (step #{s.step}):"
|
539
|
+
p s.state.to_h
|
379
540
|
sleep 5
|
380
541
|
end
|
381
542
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: y_petri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- boris
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|