y_petri 2.0.7 → 2.0.14.p1
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/net/selections.rb +209 -0
- data/lib/y_petri/net/visualization.rb +67 -0
- data/lib/y_petri/net.rb +33 -311
- data/lib/y_petri/place/guard.rb +20 -13
- data/lib/y_petri/place.rb +12 -7
- data/lib/y_petri/simulation.rb +8 -9
- data/lib/y_petri/transition/assignment.rb +37 -0
- data/lib/y_petri/transition/{constructor_syntax.rb → construction.rb} +1 -0
- data/lib/y_petri/transition/ordinary_timeless.rb +46 -0
- data/lib/y_petri/transition/timed.rb +57 -0
- data/lib/y_petri/transition.rb +103 -220
- data/lib/y_petri/version.rb +1 -1
- data/lib/y_petri.rb +1 -1
- data/test/acceptance/basic_usage_test.rb +30 -0
- data/test/acceptance/simulation_test.rb +132 -0
- data/test/acceptance/simulation_with_physical_units_test.rb +153 -0
- data/test/acceptance/token_game_test.rb +36 -0
- data/test/acceptance/visualization_test.rb +25 -0
- data/test/acceptance_tests.rb +14 -0
- data/test/manipulator_test.rb +100 -0
- data/test/{simple_manual_examples.rb → manual_examples.rb} +0 -0
- data/test/net_test.rb +171 -0
- data/test/place_test.rb +7 -6
- data/test/simulation_test.rb +280 -0
- data/test/timed_simulation_test.rb +149 -0
- data/test/transition_test.rb +2 -4
- data/test/workspace_test.rb +72 -0
- data/test/y_petri_test.rb +16 -1107
- metadata +34 -7
@@ -0,0 +1,280 @@
|
|
1
|
+
#! /usr/bin/ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
require 'minitest/spec'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require_relative '../lib/y_petri' # tested component itself
|
7
|
+
# require 'y_petri'
|
8
|
+
# require 'sy'
|
9
|
+
|
10
|
+
describe ::YPetri::Simulation do
|
11
|
+
before do
|
12
|
+
@pç = pç = Class.new( ::YPetri::Place )
|
13
|
+
@tç = tç = Class.new( ::YPetri::Transition )
|
14
|
+
@nç = nç = Class.new( ::YPetri::Net )
|
15
|
+
[ @pç, @tç, @nç ].each { |klass|
|
16
|
+
klass.namespace!.class_exec {
|
17
|
+
private
|
18
|
+
define_method :Place do pç end
|
19
|
+
define_method :Transition do tç end
|
20
|
+
define_method :Net do nç end
|
21
|
+
}
|
22
|
+
}
|
23
|
+
@p1 = @pç.new name: "P1", default_marking: 1
|
24
|
+
@p2 = @pç.new name: "P2", default_marking: 2
|
25
|
+
@p3 = @pç.new name: "P3", default_marking: 3
|
26
|
+
@p4 = @pç.new name: "P4", default_marking: 4
|
27
|
+
@p5 = @pç.new name: "P5", default_marking: 5
|
28
|
+
@t1 = @tç.new name: "T1",
|
29
|
+
s: { @p1 => -1, @p2 => -1, @p4 => 1 },
|
30
|
+
rate: 0.1
|
31
|
+
@t2 = @tç.new name: "T2",
|
32
|
+
s: { @p1 => -1, @p3 => 1 },
|
33
|
+
rate: -> a { a * 0.5 }
|
34
|
+
@t3 = @tç.new name: "T3",
|
35
|
+
s: { @p1 => -1, @p2 => -1, @p4 => 1 },
|
36
|
+
domain: @p3,
|
37
|
+
rate: -> a { a * 0.5 }
|
38
|
+
@net = @nç.new << @p1 << @p2 << @p3 << @p4 << @p5
|
39
|
+
@net.include_transition! @t1
|
40
|
+
@net.include_transition! @t2
|
41
|
+
@net << @t3
|
42
|
+
@s = YPetri::Simulation.new net: @net,
|
43
|
+
marking_clamps: { @p1 => 2.0, @p5 => 2.0 },
|
44
|
+
initial_marking: { @p2 => @p2.default_marking,
|
45
|
+
@p3 => @p3.default_marking,
|
46
|
+
@p4 => @p4.default_marking }
|
47
|
+
end
|
48
|
+
|
49
|
+
it "exposes the net" do
|
50
|
+
@s.net.must_equal @net
|
51
|
+
@s.net.places.size.must_equal 5
|
52
|
+
@s.net.transitions.size.must_equal 3
|
53
|
+
assert @net.include? @t1
|
54
|
+
assert @s.net.include? @t1
|
55
|
+
assert @net.include? @t2
|
56
|
+
assert @s.net.include? @t2
|
57
|
+
assert @net.include? @t3
|
58
|
+
assert @s.net.include? @t3
|
59
|
+
@s.net.transitions.size.must_equal 3
|
60
|
+
end
|
61
|
+
|
62
|
+
it "exposes Petri net places" do
|
63
|
+
@s.places.must_equal [ @p1, @p2, @p3, @p4, @p5 ]
|
64
|
+
@s.pp.must_equal [ :P1, :P2, :P3, :P4, :P5 ]
|
65
|
+
@s.places( :pp ).must_equal( { @p1 => :P1, @p2 => :P2, @p3 => :P3,
|
66
|
+
@p4 => :P4, @p5 => :P5 } )
|
67
|
+
@s.pp( :pp ).must_equal( { P1: :P1, P2: :P2, P3: :P3, P4: :P4, P5: :P5 } )
|
68
|
+
end
|
69
|
+
|
70
|
+
it "exposes Petri net transitions" do
|
71
|
+
@s.transitions.must_equal [ @t1, @t2, @t3 ]
|
72
|
+
@s.tt.must_equal [ :T1, :T2, :T3 ]
|
73
|
+
@s.transitions( :tt ).must_equal( { @t1 => :T1, @t2 => :T2, @t3 => :T3 } )
|
74
|
+
@s.tt( :tt ).must_equal( { T1: :T1, T2: :T2, T3: :T3 } )
|
75
|
+
end
|
76
|
+
|
77
|
+
it "exposes place clamps" do
|
78
|
+
@s.clamped_places( :place_clamps ).must_equal( { @p1 => 2, @p5 => 2 } )
|
79
|
+
@s.clamped_pp( :place_clamps ).must_equal( { P1: 2, P5: 2 } )
|
80
|
+
end
|
81
|
+
|
82
|
+
it "presents free places" do
|
83
|
+
@s.free_places.must_equal [ @p2, @p3, @p4 ]
|
84
|
+
@s.free_pp.must_equal [ :P2, :P3, :P4 ]
|
85
|
+
@s.free_places( :free_pp )
|
86
|
+
.must_equal( { @p2 => :P2, @p3 => :P3, @p4 => :P4 } )
|
87
|
+
@s.free_pp( :free_pp )
|
88
|
+
.must_equal( { P2: :P2, P3: :P3, P4: :P4 } )
|
89
|
+
end
|
90
|
+
|
91
|
+
it "presents clamped places" do
|
92
|
+
@s.clamped_places.must_equal [ @p1, @p5 ]
|
93
|
+
@s.clamped_pp.must_equal [ :P1, :P5 ]
|
94
|
+
@s.clamped_places( :clamped_pp ).must_equal( { @p1 => :P1, @p5 => :P5 } )
|
95
|
+
@s.clamped_pp( :clamped_pp ).must_equal( { P1: :P1, P5: :P5 } )
|
96
|
+
end
|
97
|
+
|
98
|
+
it "exposes initial marking" do
|
99
|
+
@s.free_places( :im ).must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
|
100
|
+
@s.free_pp( :im ).must_equal( { P2: 2, P3: 3, P4: 4 } )
|
101
|
+
@s.im.must_equal [ 2, 3, 4 ]
|
102
|
+
@s.im_vector.must_equal Matrix[[2], [3], [4]]
|
103
|
+
@s.im_vector.must_equal @s.iᴍ
|
104
|
+
end
|
105
|
+
|
106
|
+
it "exposes marking (simulation state)" do
|
107
|
+
@s.m.must_equal [2, 3, 4] # (we're after reset)
|
108
|
+
@s.free_places( :m ).must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
|
109
|
+
@s.free_pp( :m ).must_equal( { P2: 2, P3: 3, P4: 4 } )
|
110
|
+
@s.ᴍ.must_equal Matrix[[2], [3], [4]]
|
111
|
+
end
|
112
|
+
|
113
|
+
it "separately exposes marking of clamped places" do
|
114
|
+
@s.m_clamped.must_equal [ 2, 2 ]
|
115
|
+
@s.clamped_places( :m_clamped ).must_equal( { @p1 => 2, @p5 => 2 } )
|
116
|
+
@s.clamped_pp( :m_clamped ).must_equal( { P1: 2, P5: 2 } )
|
117
|
+
@s.ᴍ_clamped.must_equal Matrix[[2], [2]]
|
118
|
+
end
|
119
|
+
|
120
|
+
it "exposes marking of all places (with capitalized M)" do
|
121
|
+
@s.marking.must_equal [ 2, 2, 3, 4, 2 ]
|
122
|
+
@s.places( :marking )
|
123
|
+
.must_equal( { @p1 => 2, @p2 => 2, @p3 => 3, @p4 => 4, @p5 => 2 } )
|
124
|
+
@s.pp( :marking ).must_equal( { P1: 2, P2: 2, P3: 3, P4: 4, P5: 2 } )
|
125
|
+
@s.marking_vector.must_equal Matrix[[2], [2], [3], [4], [2]]
|
126
|
+
end
|
127
|
+
|
128
|
+
it "has #S_for / #stoichiometry_matrix_for" do
|
129
|
+
assert_equal Matrix.empty(3, 0), @s.S_for( [] )
|
130
|
+
assert_equal Matrix[[-1], [0], [1]], @s.S_for( [@t1] )
|
131
|
+
x = Matrix[[-1, -1], [0, 0], [1, 1]]
|
132
|
+
x.must_equal @s.S_for( [@t1, @t3] )
|
133
|
+
x.must_equal( @s.S_for( [@t1, @t3] ) )
|
134
|
+
@s.stoichiometry_matrix_for( [] ).must_equal Matrix.empty( 5, 0 )
|
135
|
+
end
|
136
|
+
|
137
|
+
it "has stoichiometry matrix for 3. tS transitions" do
|
138
|
+
@s.S_for_tS.must_equal Matrix.empty( 3, 0 )
|
139
|
+
end
|
140
|
+
|
141
|
+
it "has stoichiometry matrix for 4. Sr transitions" do
|
142
|
+
@s.S_for_TSr.must_equal Matrix.empty( 3, 0 )
|
143
|
+
end
|
144
|
+
|
145
|
+
it "has stoichiometry matrix for 6. SR transitions" do
|
146
|
+
@s.S_for_SR.must_equal Matrix[[-1, 0, -1], [0, 1, 0], [1, 0, 1]]
|
147
|
+
@s.S.must_equal @s.S_for_SR
|
148
|
+
end
|
149
|
+
|
150
|
+
it "presents 1. ts" do
|
151
|
+
assert_equal [], @s.ts_transitions
|
152
|
+
assert_equal( {}, @s.ts_transitions( :ts_transitions ) )
|
153
|
+
assert_equal [], @s.ts_tt
|
154
|
+
assert_equal( {}, @s.ts_tt( :ts_tt ) )
|
155
|
+
end
|
156
|
+
|
157
|
+
it "presents 2. tS transitions" do
|
158
|
+
assert_equal [], @s.tS_transitions
|
159
|
+
assert_equal( {}, @s.tS_transitions( :tS_transitions ) )
|
160
|
+
assert_equal [], @s.tS_tt
|
161
|
+
assert_equal( {}, @s.tS_tt( :tS_tt ) )
|
162
|
+
end
|
163
|
+
|
164
|
+
it "presents 3. Tsr transitions" do
|
165
|
+
assert_equal [], @s.Tsr_transitions
|
166
|
+
assert_equal( {}, @s.Tsr_transitions( :Tsr_transitions ) )
|
167
|
+
assert_equal [], @s.Tsr_tt
|
168
|
+
assert_equal( {}, @s.Tsr_tt( :Tsr_tt ) )
|
169
|
+
end
|
170
|
+
|
171
|
+
it "presents 4. TSr transitions" do
|
172
|
+
assert_equal [], @s.TSr_transitions
|
173
|
+
assert_equal( {}, @s.TSr_transitions( :TSr_tt ) )
|
174
|
+
assert_equal [], @s.TSr_tt
|
175
|
+
assert_equal( {}, @s.TSr_tt( :TSr_tt ) )
|
176
|
+
end
|
177
|
+
|
178
|
+
it "presents 5. sR transitions" do
|
179
|
+
assert_equal [], @s.sR_transitions
|
180
|
+
assert_equal( {}, @s.sR_transitions( :sR_transitions ) )
|
181
|
+
assert_equal [], @s.sR_tt
|
182
|
+
assert_equal( {}, @s.sR_tt( :sR_tt ) )
|
183
|
+
end
|
184
|
+
|
185
|
+
it "presents SR transitions" do
|
186
|
+
assert_equal [@t1, @t2, @t3], @s.SR_transitions
|
187
|
+
assert_equal( { @t1 => :T1, @t2 => :T2, @t3 => :T3 },
|
188
|
+
@s.SR_transitions( :SR_tt ) )
|
189
|
+
assert_equal [:T1, :T2, :T3], @s.SR_tt
|
190
|
+
assert_equal( { T1: :T1, T2: :T2, T3: :T3 }, @s.SR_tt( :SR_tt ) )
|
191
|
+
end
|
192
|
+
|
193
|
+
it "presents A transitions" do
|
194
|
+
assert_equal [], @s.A_transitions
|
195
|
+
assert_equal( {}, @s.A_transitions( :A_tt ) )
|
196
|
+
assert_equal [], @s.A_tt
|
197
|
+
assert_equal( {}, @s.A_tt( :A_tt ) )
|
198
|
+
end
|
199
|
+
|
200
|
+
it "presents S transitions" do
|
201
|
+
assert_equal [@t1, @t2, @t3], @s.S_transitions
|
202
|
+
assert_equal [:T1, :T2, :T3], @s.S_tt
|
203
|
+
assert_equal( { T1: :T1, T2: :T2, T3: :T3 }, @s.S_tt( :S_tt ) )
|
204
|
+
end
|
205
|
+
|
206
|
+
it "presents s transitions" do
|
207
|
+
assert_equal [], @s.s_transitions
|
208
|
+
assert_equal [], @s.s_tt
|
209
|
+
assert_equal( {}, @s.s_tt( :s_tt ) )
|
210
|
+
end
|
211
|
+
|
212
|
+
it "presents R transitions" do
|
213
|
+
assert_equal [@t1, @t2, @t3], @s.R_transitions
|
214
|
+
assert_equal [:T1, :T2, :T3], @s.R_tt
|
215
|
+
assert_equal( { T1: :T1, T2: :T2, T3: :T3 }, @s.R_tt( :R_tt ) )
|
216
|
+
end
|
217
|
+
|
218
|
+
it "presents r transitions" do
|
219
|
+
assert_equal [], @s.r_transitions
|
220
|
+
assert_equal [], @s.r_tt
|
221
|
+
end
|
222
|
+
|
223
|
+
it "1. handles ts transitions" do
|
224
|
+
@s.Δ_closures_for_tsa.must_equal []
|
225
|
+
@s.Δ_if_tsa_fire_once.must_equal Matrix.zero( @s.free_pp.size, 1 )
|
226
|
+
end
|
227
|
+
|
228
|
+
it "2. handles Tsr transitions" do
|
229
|
+
@s.Δ_closures_for_Tsr.must_equal []
|
230
|
+
@s.Δ_for_Tsr( 1.0 ).must_equal Matrix.zero( @s.free_pp.size, 1 )
|
231
|
+
end
|
232
|
+
|
233
|
+
it "3. handles tS transitions" do
|
234
|
+
@s.action_closures_for_tS.must_equal []
|
235
|
+
@s.action_vector_for_tS.must_equal Matrix.column_vector( [] )
|
236
|
+
@s.α_for_t.must_equal Matrix.column_vector( [] )
|
237
|
+
@s.Δ_if_tS_fire_once.must_equal Matrix.zero( @s.free_pp.size, 1 )
|
238
|
+
end
|
239
|
+
|
240
|
+
it "4. handles TSr transitions" do
|
241
|
+
@s.action_closures_for_TSr.must_equal []
|
242
|
+
@s.action_closures_for_Tr.must_equal []
|
243
|
+
@s.action_vector_for_TSr( 1.0 ).must_equal Matrix.column_vector( [] )
|
244
|
+
@s.action_vector_for_Tr( 1.0 ).must_equal Matrix.column_vector( [] )
|
245
|
+
@s.Δ_for_TSr( 1.0 ).must_equal Matrix.zero( @s.free_pp.size, 1 )
|
246
|
+
end
|
247
|
+
|
248
|
+
it "5. handles sR transitions" do
|
249
|
+
assert_equal [], @s.rate_closures_for_sR
|
250
|
+
assert_equal [], @s.rate_closures_for_s
|
251
|
+
# @s.gradient_for_sR.must_equal Matrix.zero( @s.free_pp.size, 1 )
|
252
|
+
@s.Δ_Euler_for_sR( 1.0 ).must_equal Matrix.zero( @s.free_pp.size, 1 )
|
253
|
+
end
|
254
|
+
|
255
|
+
it "6. handles stoichiometric transitions with rate" do
|
256
|
+
@s.rate_closures_for_SR.size.must_equal 3
|
257
|
+
@s.rate_closures_for_S.size.must_equal 3
|
258
|
+
@s.rate_closures.size.must_equal 3
|
259
|
+
@s.flux_vector_for_SR.must_equal Matrix.column_vector( [ 0.4, 1.0, 1.5 ] )
|
260
|
+
@s.φ_for_SR.must_equal @s.flux_vector
|
261
|
+
@s.SR_tt( :φ_for_SR ).must_equal( { T1: 0.4, T2: 1.0, T3: 1.5 } )
|
262
|
+
@s.Euler_action_vector_for_SR( 1 )
|
263
|
+
.must_equal Matrix.column_vector [ 0.4, 1.0, 1.5 ]
|
264
|
+
@s.SR_tt( :Euler_action_for_SR, 1 ).must_equal( T1: 0.4, T2: 1.0, T3: 1.5 )
|
265
|
+
@s.Δ_Euler_for_SR( 1 ).must_equal Matrix[[-1.9], [1.0], [1.9]]
|
266
|
+
@s.free_pp( :Δ_Euler_for_SR, 1 ).must_equal( { P2: -1.9, P3: 1.0, P4: 1.9 } )
|
267
|
+
end
|
268
|
+
|
269
|
+
it "presents sparse stoichiometry vectors for its transitions" do
|
270
|
+
@s.sparse_σ( @t1 ).must_equal Matrix.cv( [-1, 0, 1] )
|
271
|
+
@s.sparse_stoichiometry_vector( @t1 )
|
272
|
+
.must_equal Matrix.cv( [-1, -1, 0, 1, 0] )
|
273
|
+
end
|
274
|
+
|
275
|
+
it "presents correspondence matrices free, clamped => all places" do
|
276
|
+
@s.F2A.must_equal Matrix[[0, 0, 0], [1, 0, 0], [0, 1, 0],
|
277
|
+
[0, 0, 1], [0, 0, 0]]
|
278
|
+
@s.C2A.must_equal Matrix[[1, 0], [0, 0], [0, 0], [0, 0], [0, 1]]
|
279
|
+
end
|
280
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
#! /usr/bin/ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
require 'minitest/spec'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require_relative '../lib/y_petri' # tested component itself
|
7
|
+
# require 'y_petri'
|
8
|
+
# require 'sy'
|
9
|
+
|
10
|
+
include Pyper if require 'pyper'
|
11
|
+
|
12
|
+
# **************************************************************************
|
13
|
+
# Test of TimedSimulation class.
|
14
|
+
# **************************************************************************
|
15
|
+
#
|
16
|
+
describe YPetri::TimedSimulation do
|
17
|
+
before do
|
18
|
+
# skip "to speed up testing"
|
19
|
+
@a = YPetri::Place.new default_marking: 1.0
|
20
|
+
@b = YPetri::Place.new default_marking: 2.0
|
21
|
+
@c = YPetri::Place.new default_marking: 3.0
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "timed assembly a + b >> c" do
|
25
|
+
before do
|
26
|
+
@t1 = YPetri::Transition.new s: { @a => -1, @b => -1, @c => 1 }, rate: 0.1
|
27
|
+
@net = YPetri::Net.new << @a << @b << @c << @t1
|
28
|
+
@im_collection = [@a, @b, @c].τBmχHτ &:default_marking
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "simulation with step size 1" do
|
32
|
+
before do
|
33
|
+
@sim = YPetri::TimedSimulation.new net: @net,
|
34
|
+
initial_marking: @im_collection,
|
35
|
+
step: 1,
|
36
|
+
sampling: 10,
|
37
|
+
target_time: 100
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should #step! with expected results" do
|
41
|
+
m = @sim.step!.marking
|
42
|
+
assert_in_delta 0.8, m[ 0 ], 1e-9
|
43
|
+
assert_in_delta 1.8, m[ 1 ], 1e-9
|
44
|
+
assert_in_delta 3.2, m[ 2 ], 1e-9
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should behave" do
|
48
|
+
assert_in_delta 0, ( Matrix.column_vector( [-0.02, -0.02, 0.02] ) -
|
49
|
+
@sim.ΔE( 0.1 ) ).column( 0 ).norm, 1e-9
|
50
|
+
@sim.step! 0.1
|
51
|
+
assert_in_delta 0, ( Matrix.column_vector( [0.98, 1.98, 3.02] ) -
|
52
|
+
@sim.marking_vector ).column( 0 ).norm, 1e-9
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "simulation with step size 0.1" do
|
58
|
+
before do
|
59
|
+
@sim = YPetri::TimedSimulation.new net: @net,
|
60
|
+
initial_marking: @im_collection,
|
61
|
+
step: 0.1,
|
62
|
+
sampling: 10,
|
63
|
+
target_time: 100
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should behave" do
|
67
|
+
m = @sim.step!.marking
|
68
|
+
assert_equal 10, @sim.sampling_period
|
69
|
+
assert_in_delta 0.98, m[ 0 ], 1e-9
|
70
|
+
assert_in_delta 1.98, m[ 1 ], 1e-9
|
71
|
+
assert_in_delta 3.02, m[ 2 ], 1e-9
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should behave" do
|
75
|
+
@sim.run_until_target_time! 31
|
76
|
+
expected_recording = {
|
77
|
+
0 => [ 1, 2, 3 ],
|
78
|
+
10 => [ 0.22265, 1.22265, 3.77735 ],
|
79
|
+
20 => [ 0.07131, 1.07131, 3.92869 ],
|
80
|
+
30 => [ 0.02496, 1.02496, 3.97503 ]
|
81
|
+
}
|
82
|
+
assert_equal expected_recording.keys, @sim.recording.keys
|
83
|
+
assert_in_delta 0, expected_recording.values.zip( @sim.recording.values )
|
84
|
+
.map{ |expected, actual| ( Vector[ *expected ] -
|
85
|
+
Vector[ *actual ] ).norm }.reduce( :+ ), 1e-4
|
86
|
+
expected_recording_string =
|
87
|
+
"0.0,1.0,2.0,3.0\n" +
|
88
|
+
"10.0,0.22265,1.22265,3.77735\n" +
|
89
|
+
"20.0,0.07131,1.07131,3.92869\n" +
|
90
|
+
"30.0,0.02496,1.02496,3.97504\n"
|
91
|
+
assert_equal expected_recording_string, @sim.recording_csv_string
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "timed 'isomerization' with given as λ" do
|
97
|
+
before do
|
98
|
+
@t2 = YPetri::Transition.new s: { @a => -1, @c => 1 },
|
99
|
+
rate_closure: -> a { a * 0.5 }
|
100
|
+
@net = YPetri::Net.new << @a << @b << @c << @t2
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "behavior of #step" do
|
104
|
+
before do
|
105
|
+
@sim = YPetri::TimedSimulation.new net: @net,
|
106
|
+
initial_marking: [ @a, @b, @c ].τBᴍHτ( &:default_marking ),
|
107
|
+
step: 1,
|
108
|
+
sampling: 10
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should have expected stoichiometry matrix" do
|
112
|
+
@sim.S.must_equal Matrix[ [-1, 0, 1] ].t
|
113
|
+
m = @sim.step!.marking
|
114
|
+
m[ 0 ].must_be_within_epsilon( 0.5, 1e-6 )
|
115
|
+
m[ 1 ].must_equal 2
|
116
|
+
m[ 2 ].must_be_within_delta( 3.5, 1e-9 )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "timed controlled isomerization" do
|
122
|
+
before do
|
123
|
+
@t3 = YPetri::Transition.new s: { @a => -1, @c => 1 },
|
124
|
+
domain: @b,
|
125
|
+
rate: -> a { a * 0.5 }
|
126
|
+
@net = YPetri::Net.new << @a << @b << @c << @t3
|
127
|
+
@sim = YPetri::TimedSimulation.new net: @net,
|
128
|
+
initial_marking: { @a => 1, @b => 0.6, @c => 3 },
|
129
|
+
step: 1,
|
130
|
+
sampling: 10,
|
131
|
+
target_time: 2
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should exhibit correct behavior of #step" do
|
135
|
+
@sim.marking.must_equal [1.0, 0.6, 3.0]
|
136
|
+
@t3.stoichiometric?.must_equal true
|
137
|
+
@t3.timed?.must_equal true
|
138
|
+
@t3.has_rate?.must_equal true
|
139
|
+
@sim.gradient.must_equal Matrix.cv [-0.3, 0.0, 0.3]
|
140
|
+
@sim.Δ_Euler.must_equal Matrix.cv [-0.3, 0.0, 0.3]
|
141
|
+
@sim.step!
|
142
|
+
@sim.marking_vector.must_equal Matrix.cv [0.7, 0.6, 3.3]
|
143
|
+
@sim.euler_step!
|
144
|
+
@sim.run!
|
145
|
+
@sim.marking_vector.map( &[:round, 5] )
|
146
|
+
.must_equal Matrix.cv [0.4, 0.6, 3.6]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/test/transition_test.rb
CHANGED
@@ -155,15 +155,13 @@ describe ::YPetri::Transition do
|
|
155
155
|
assert @tt.all? { |t| t.action == [1] }
|
156
156
|
# #zero_action
|
157
157
|
assert @tt.all? { |t| t.zero_action }
|
158
|
-
# #action_after_feasibility_check
|
159
|
-
assert @tt.all? { |t| t.action_after_feasibility_check == [1] }
|
160
158
|
# #domain_marking
|
161
159
|
assert @tt.all? { |t| t.domain_marking == [] }
|
162
160
|
# #codomain_marking
|
163
161
|
assert @tt.all? { |t| t.codomain_marking == [@p1.m] }
|
164
162
|
# #enabled?
|
165
163
|
@p1.m.must_equal 1
|
166
|
-
@p1.guard.( 1 ).must_equal
|
164
|
+
@p1.guard.( 1 ).must_equal 1
|
167
165
|
@tt.each { |t| t.enabled?.must_equal true }
|
168
166
|
end
|
169
167
|
end
|
@@ -248,7 +246,7 @@ describe ::YPetri::Transition do
|
|
248
246
|
@SR2.fire! 1.0
|
249
247
|
[@p1, @p3].map( &:marking ).must_equal [0.4, 3.4]
|
250
248
|
# the action t3 cannot fire with delta time 1.0
|
251
|
-
-> { @SR3.fire! 1.0 }.must_raise
|
249
|
+
-> { @SR3.fire! 1.0 }.must_raise YPetri::GuardError
|
252
250
|
[@p1, @p2, @p3, @p4].map( &:marking ).must_equal [0.4, 1.8, 3.4, 4.2]
|
253
251
|
# but it can fire with eg. delta time 0.1
|
254
252
|
@SR3.fire! 0.1
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#! /usr/bin/ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
require 'minitest/spec'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require_relative '../lib/y_petri' # tested component itself
|
7
|
+
# require 'y_petri'
|
8
|
+
# require 'sy'
|
9
|
+
|
10
|
+
include Pyper if require 'pyper'
|
11
|
+
|
12
|
+
describe YPetri::Workspace do
|
13
|
+
before do
|
14
|
+
@w = YPetri::Workspace.new
|
15
|
+
a = @w.Place.new!( default_marking: 1.0, name: "AA" )
|
16
|
+
b = @w.Place.new!( default_marking: 2.0, name: "BB" )
|
17
|
+
c = @w.Place.new!( ɴ: "CC", default_marking: 3.0 )
|
18
|
+
t1 = @w.Transition.new! s: { a => -1, b => -1, c => 1 },
|
19
|
+
rate: 0.1,
|
20
|
+
ɴ: "AA_BB_assembly"
|
21
|
+
t2 = @w.Transition.new! ɴ: "AA_appearing",
|
22
|
+
codomain: a,
|
23
|
+
rate: -> { 0.1 },
|
24
|
+
stoichiometry: 1
|
25
|
+
@pp, @tt = [a, b, c], [t1, t2]
|
26
|
+
@f_name = "test_output.csv"
|
27
|
+
@w.set_imc @pp.τBᴍHτ( &:default_marking )
|
28
|
+
@w.set_ssc step: 0.1, sampling: 10, target_time: 50
|
29
|
+
@w.set_cc( {} )
|
30
|
+
@sim = @w.new_timed_simulation
|
31
|
+
File.delete @f_name rescue nil
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should present places, transitions, nets, simulations" do
|
35
|
+
assert_kind_of YPetri::Net, @w.Net::Top
|
36
|
+
assert_equal @pp[0], @w.place( "AA" )
|
37
|
+
assert_equal :AA, @w.pl( @pp[0] )
|
38
|
+
assert_equal @tt[0], @w.transition( "AA_BB_assembly" )
|
39
|
+
assert_equal :AA_appearing, @w.tr( @tt[1] )
|
40
|
+
assert_equal @pp, @w.places
|
41
|
+
assert_equal @tt, @w.transitions
|
42
|
+
assert_equal 1, @w.nets.size
|
43
|
+
assert_equal 1, @w.simulations.size
|
44
|
+
assert_equal 0, @w.cc.size
|
45
|
+
assert_equal 3, @w.imc.size
|
46
|
+
assert [0.1, 10, 50].each { |e| @w.ssc.include? e }
|
47
|
+
assert_equal @sim, @w.simulation
|
48
|
+
assert_equal [:Base], @w.clamp_collections.keys
|
49
|
+
assert_equal [:Base], @w.initial_marking_collections.keys
|
50
|
+
assert_equal [:Base], @w.simulation_settings_collections.keys
|
51
|
+
assert_equal [:AA, :BB, :CC], @w.pp
|
52
|
+
assert_equal [:AA_BB_assembly, :AA_appearing], @w.tt
|
53
|
+
assert_equal [:Top], @w.nn
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should simulate" do
|
57
|
+
assert_equal 1, @w.simulations.size
|
58
|
+
assert_kind_of( YPetri::Simulation, @w.simulation )
|
59
|
+
assert_equal 2, @w.simulation.SR_transitions.size
|
60
|
+
@tt[0].domain.must_equal [ @pp[0], @pp[1] ]
|
61
|
+
@tt[1].domain.must_equal []
|
62
|
+
assert_equal [0.2, 0.1], @w.simulation.φ.column_to_a
|
63
|
+
@w.simulation.step!
|
64
|
+
@w.simulation.run!
|
65
|
+
rec_string = @w.simulation.recording_csv_string
|
66
|
+
expected_recording_string =
|
67
|
+
"0.0,1.0,2.0,3.0\n" +
|
68
|
+
"10.0,0.86102,0.86102,4.13898\n" +
|
69
|
+
"20.0,1.29984,0.29984,4.70016\n"
|
70
|
+
assert rec_string.start_with?( expected_recording_string )
|
71
|
+
end
|
72
|
+
end
|