test/simulation_test.rb in y_petri-2.3.12 vs test/simulation_test.rb in y_petri-2.4.0

- old
+ new

@@ -319,63 +319,224 @@ # tmp.must_equal( { 0 => [2.5, 1], 1 => [2.5, 1], 2 => [2.5, 1], # 3 => [2.5, 1], 4 => [2.5, 1], 5 => [2.5, 1] } ) # end # end -describe "timed simulation" do +# describe "timed simulation" do +# before do +# self.class.class_exec { include YPetri } +# A = Place m!: 0.5 +# B = Place m!: 0.5 +# A_pump = TT s: { A: -1 } do 0.005 end +# B_decay = Transition s: { B: -1 }, rate: 0.05 +# run! +# end + +# it "should work with the default method" do +# places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected +# s = simulation +# s.settings.must_equal( { method: :basic, guarded: false, +# step: 0.1, sampling: 5, time: 0..60 } ) +# assert s.recording.to_csv.start_with?( ":event,:A,:B\n" + +# "0.0,0.5,0.5\n" + +# "5.0,0.475,0.38916\n" + +# "10.0,0.45,0.30289\n" + +# "15.0,0.425,0.23574\n" + +# "20.0,0.4,0.18348\n" + +# "25.0,0.375,0.1428\n" ) +# assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" ) +# s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0, +# 25.0, 30.0, 35.0, 40.0, 45.0, +# 50.0, 55.0, 60.0 ] +# s.recording.values_at( 5, 10 ) +# .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ] +# s.recording.slice( 2..12 ) +# .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } ) +# s.recording.net +# .must_equal net +# s.recording.features +# .must_equal net.State.Features.marking( :A, :B ) +# net.State.Features.State +# .must_equal net.State +# s.recording.net.State +# .must_equal net.State +# s.recording.series( marking: [:A] ) +# .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325, +# 0.3, 0.275, 0.25, 0.225, 0.2 ] ] +# s.net.State.Features.firing.map( &:transition ).names +# .must_equal [ :A_pump, :B_decay ] +# s.recording.reduce_features( s.net.State.Features.firing, Δt: 1 ) +# .to_h.take( 2 ).map( &:flatten! ).map { |a| a.map &[:round, 6 ] } +# .must_equal [ [ 0.0, 0.005, 0.025 ], [ 5.0, 0.005, 0.019458 ] ] +# s.recording.firing( Δt: 0.1 ).series.map( &:first ).map( &[ :round, 6 ] ) +# .must_equal [ 0.0005, 0.0025 ] +# s.recording.Firing( [] ) +# .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 ) +# s.recording +# .delta( :A, transitions: [:A_pump], delta_time: 0.1 ) +# .series +# .must_equal [ [ -0.0005 ] * 13 ] +# plot_state +# sleep 5 +# end +# end + +describe "timed simulation with other methods" do before do self.class.class_exec { include YPetri } - A = Place m!: 0.5 - B = Place m!: 0.5 - A_pump = TT s: { A: -1 } do 0.005 end - B_decay = Transition s: { B: -1 }, rate: 0.05 - run! + A = Place m!: 0.5 unless places.names.include? :A + B = Place m!: 0.5 unless places.names.include? :B + A_pump = TT s: { A: -1 } do 0.005 end unless transitions.names.include? :A_pump + B_decay = Transition s: { B: -1 }, rate: 0.05 unless transitions.names.include? :B_decay end - it "should behave" do - places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected - s = simulation - s.settings.must_equal( { method: :basic, guarded: false, - step: 0.1, sampling: 5, time: 0..60 } ) - assert s.recording.to_csv.start_with?( ":event,:A,:B\n" + - "0.0,0.5,0.5\n" + - "5.0,0.475,0.38916\n" + - "10.0,0.45,0.30289\n" + - "15.0,0.425,0.23574\n" + - "20.0,0.4,0.18348\n" + - "25.0,0.375,0.1428\n" ) - assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" ) - s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0, - 25.0, 30.0, 35.0, 40.0, 45.0, - 50.0, 55.0, 60.0 ] - s.recording.values_at( 5, 10 ) - .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ] - s.recording.slice( 2..12 ) - .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } ) - s.recording.net - .must_equal net - s.recording.features - .must_equal net.State.Features.marking( :A, :B ) - net.State.Features.State - .must_equal net.State - s.recording.net.State - .must_equal net.State - s.recording.series( marking: [:A] ) - .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325, - 0.3, 0.275, 0.25, 0.225, 0.2 ] ] - s.net.State.Features.firing.map( &:transition ).names - .must_equal [ :A_pump, :B_decay ] - s.recording.reduce_features( s.net.State.Features.firing, Δt: 1 ) - .to_h.take( 2 ).map( &:flatten! ).map { |a| a.map &[:round, 6 ] } - .must_equal [ [ 0.0, 0.005, 0.025 ], [ 5.0, 0.005, 0.019458 ] ] - s.recording.firing( Δt: 0.1 ).series.map( &:first ).map( &[ :round, 6 ] ) - .must_equal [ 0.0005, 0.0025 ] - s.recording.Firing( [] ) - .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 ) - s.recording - .delta( :A, transitions: [:A_pump], delta_time: 0.1 ) - .series - .must_equal [ [ -0.0005 ] * 13 ] + # it "should work with the default method" do + # basic_simulation = new_simulation + # s = basic_simulation + # s.run! + # places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected + # s.settings.must_equal( { method: :basic, guarded: false, + # step: 0.1, sampling: 5, time: 0..60 } ) + # assert s.recording.to_csv.start_with?( ":event,:A,:B\n" + + # "0.0,0.5,0.5\n" + + # "5.0,0.475,0.38916\n" + + # "10.0,0.45,0.30289\n" + + # "15.0,0.425,0.23574\n" + + # "20.0,0.4,0.18348\n" + + # "25.0,0.375,0.1428\n" ) + # assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" ) + # s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0, + # 25.0, 30.0, 35.0, 40.0, 45.0, + # 50.0, 55.0, 60.0 ] + # s.recording.values_at( 5, 10 ) + # .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ] + # s.recording.slice( 2..12 ) + # .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } ) + # s.recording.net + # .must_equal net + # s.recording.features + # .must_equal net.State.Features.marking( :A, :B ) + # net.State.Features.State + # .must_equal net.State + # s.recording.net.State + # .must_equal net.State + # s.recording.series( marking: [:A] ) + # .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325, + # 0.3, 0.275, 0.25, 0.225, 0.2 ] ] + # s.net.State.Features.firing.map( &:transition ).names + # .must_equal [ :A_pump, :B_decay ] + # s.recording.reduce_features( s.net.State.Features.firing, Δt: 1 ) + # .to_h.take( 2 ).map( &:flatten! ).map { |a| a.map &[:round, 6 ] } + # .must_equal [ [ 0.0, 0.005, 0.025 ], [ 5.0, 0.005, 0.019458 ] ] + # s.recording.firing( Δt: 0.1 ).series.map( &:first ).map( &[ :round, 6 ] ) + # .must_equal [ 0.0005, 0.0025 ] + # s.recording.Firing( [] ) + # .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 ) + # s.recording + # .delta( :A, transitions: [:A_pump], delta_time: 0.1 ) + # .series + # .must_equal [ [ -0.0005 ] * 13 ] + # plot_state + # sleep 5 + # end + + # it "should work with :runge_kutta method" do + # rk_simulation = new_simulation( method: :runge_kutta ) + # s = rk_simulation + # s.run! + # places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected + # s.settings.must_equal( { method: :runge_kutta, guarded: false, + # step: 0.1, sampling: 5, time: 0..60 } ) + # assert s.recording.to_csv.start_with?( ":event,:A,:B\n" + + # "0.0,0.5,0.5\n" + + # "5.0,0.475,0.38916\n" + + # "10.0,0.45,0.30289\n" + + # "15.0,0.425,0.23574\n" + + # "20.0,0.4,0.18348\n" + + # "25.0,0.375,0.1428\n" ) + # assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" ) + # s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0, + # 25.0, 30.0, 35.0, 40.0, 45.0, + # 50.0, 55.0, 60.0 ] + # s.recording.values_at( 5, 10 ) + # .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ] + # s.recording.slice( 2..12 ) + # .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } ) + # s.recording.net + # .must_equal net + # s.recording.features + # .must_equal net.State.Features.marking( :A, :B ) + # net.State.Features.State + # .must_equal net.State + # s.recording.net.State + # .must_equal net.State + # s.recording.series( marking: [:A] ) + # .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325, + # 0.3, 0.275, 0.25, 0.225, 0.2 ] ] + # s.net.State.Features.firing.map( &:transition ).names + # .must_equal [ :A_pump, :B_decay ] + # s.recording.reduce_features( s.net.State.Features.firing, Δt: 1 ) + # .to_h.take( 2 ).map( &:flatten! ).map { |a| a.map &[:round, 6 ] } + # .must_equal [ [ 0.0, 0.005, 0.025 ], [ 5.0, 0.005, 0.019458 ] ] + # s.recording.firing( Δt: 0.1 ).series.map( &:first ).map( &[ :round, 6 ] ) + # .must_equal [ 0.0005, 0.0025 ] + # s.recording.Firing( [] ) + # .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 ) + # s.recording + # .delta( :A, transitions: [:A_pump], delta_time: 0.1 ) + # .series + # .must_equal [ [ -0.0005 ] * 13 ] + # plot_state + # sleep 5 + # end +end + +describe "timed simulation with other methods" do + before do + self.class.class_exec { include YPetri } + A = Place m!: 0.5 unless places.names.include? :A + B = Place m!: 0.5 unless places.names.include? :B + A_pump = TT s: { A: -1 } do 0.005 end unless transitions.names.include? :A_pump + B_decay = Transition s: { B: -1 }, rate: 0.05 unless transitions.names.include? :B_decay + end + + it "should work with :runge_kutta method" do + rk_simulation = new_simulation( method: :runge_kutta ) + s = rk_simulation + s.state.to_a.must_equal [ 0.5, 0.5 ] + c = s.rk_core + c.must_be_kind_of YPetri::Core::Timed + c.marking_of_free_places.annotation.names.must_equal c.free_pp.names + c.marking_of_clamped_places.annotation.names.must_equal c.clamped_pp.names + c.simulation_method.must_equal :runge_kutta + c.marking_of_free_places.reset! [ 1.5, 1.5 ] + c.reset_time! 1.5 + c.time.must_equal 1.5 + c.state.to_a.must_equal [ 1.5, 1.5 ] + x = [] + c.set_user_alert_closure do |mv| x << mv.to_a; x.flatten end + c.step! 2.0 + c.time.must_equal 3.5 + c.state.to_a.must_equal [ 1.49, 1.35725625 ] + s.time.must_equal 0.0 + s.step.must_equal 0.1 + s.step! + s.state.to_a[ 0 ].must_equal 0.4995 + s.state.to_a[ 1 ].must_be_within_epsilon 0.49750624 + s.time.must_equal 0.1 + s.step = 5.0 + s.run! + s.time.must_equal 60.0 + puts + puts "by Runge-Kutta method (step #{s.step}):" + p s.state.to_h + s.state.to_a[ 0 ].must_be_within_epsilon 0.2 + s.state.to_a[ 1 ].must_be_within_epsilon 0.024893534 plot_state + s = new_simulation + s.run! + puts + puts "by Euler method (step #{s.step}):" + p s.state.to_h sleep 5 end end