y_petri 2.0.7 → 2.0.14.p1
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/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
|