y_petri 2.0.15 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/lib/y_petri/{manipulator → agent}/hash_key_pointer.rb +2 -2
  3. data/lib/y_petri/agent/petri_net_related.rb +115 -0
  4. data/lib/y_petri/{manipulator → agent}/selection.rb +2 -1
  5. data/lib/y_petri/{manipulator/simulation_related_methods.rb → agent/simulation_related.rb} +93 -110
  6. data/lib/y_petri/agent.rb +22 -0
  7. data/lib/y_petri/core/timed/euler.rb +20 -0
  8. data/lib/y_petri/core/timed/pseudo_euler.rb +31 -0
  9. data/lib/y_petri/core/timed/quasi_euler.rb +23 -0
  10. data/lib/y_petri/core/timed.rb +70 -0
  11. data/lib/y_petri/core/timeless/pseudo_euler.rb +20 -0
  12. data/lib/y_petri/core/timeless.rb +12 -0
  13. data/lib/y_petri/core.rb +100 -0
  14. data/lib/y_petri/dsl.rb +66 -0
  15. data/lib/y_petri/fixed_assets.rb +7 -0
  16. data/lib/y_petri/net/element_access.rb +239 -0
  17. data/lib/y_petri/net/state/feature/delta.rb +88 -0
  18. data/lib/y_petri/net/state/feature/firing.rb +57 -0
  19. data/lib/y_petri/net/state/feature/flux.rb +58 -0
  20. data/lib/y_petri/net/state/feature/gradient.rb +75 -0
  21. data/lib/y_petri/net/state/feature/marking.rb +62 -0
  22. data/lib/y_petri/net/state/feature.rb +79 -0
  23. data/lib/y_petri/net/state/features/dataset.rb +135 -0
  24. data/lib/y_petri/net/state/features/record.rb +50 -0
  25. data/lib/y_petri/net/state/features.rb +126 -0
  26. data/lib/y_petri/net/state.rb +121 -0
  27. data/lib/y_petri/net/timed.rb +8 -0
  28. data/lib/y_petri/net/visualization.rb +3 -3
  29. data/lib/y_petri/net.rb +73 -77
  30. data/lib/y_petri/place.rb +8 -3
  31. data/lib/y_petri/simulation/dependency.rb +107 -0
  32. data/lib/y_petri/simulation/element_representation.rb +20 -0
  33. data/lib/y_petri/simulation/elements/access.rb +57 -0
  34. data/lib/y_petri/simulation/elements.rb +45 -0
  35. data/lib/y_petri/simulation/feature_set.rb +21 -0
  36. data/lib/y_petri/simulation/initial_marking/access.rb +55 -0
  37. data/lib/y_petri/simulation/initial_marking.rb +15 -0
  38. data/lib/y_petri/simulation/marking_clamps/access.rb +34 -0
  39. data/lib/y_petri/simulation/marking_clamps.rb +18 -0
  40. data/lib/y_petri/simulation/marking_vector/access.rb +106 -0
  41. data/lib/y_petri/simulation/marking_vector.rb +156 -0
  42. data/lib/y_petri/simulation/matrix.rb +64 -0
  43. data/lib/y_petri/simulation/place_mapping.rb +62 -0
  44. data/lib/y_petri/simulation/place_representation.rb +74 -0
  45. data/lib/y_petri/simulation/places/access.rb +121 -0
  46. data/lib/y_petri/simulation/places/clamped.rb +8 -0
  47. data/lib/y_petri/simulation/places/free.rb +8 -0
  48. data/lib/y_petri/simulation/places/types.rb +25 -0
  49. data/lib/y_petri/simulation/places.rb +41 -0
  50. data/lib/y_petri/simulation/recorder.rb +54 -0
  51. data/lib/y_petri/simulation/timed/recorder.rb +53 -0
  52. data/lib/y_petri/simulation/timed.rb +161 -261
  53. data/lib/y_petri/simulation/timeless/recorder.rb +25 -0
  54. data/lib/y_petri/simulation/timeless.rb +35 -0
  55. data/lib/y_petri/simulation/transition_representation/A.rb +58 -0
  56. data/lib/y_petri/simulation/transition_representation/S.rb +45 -0
  57. data/lib/y_petri/simulation/transition_representation/T.rb +80 -0
  58. data/lib/y_petri/simulation/transition_representation/TS.rb +46 -0
  59. data/lib/y_petri/simulation/transition_representation/Ts.rb +32 -0
  60. data/lib/y_petri/simulation/transition_representation/a.rb +30 -0
  61. data/lib/y_petri/simulation/transition_representation/s.rb +29 -0
  62. data/lib/y_petri/simulation/transition_representation/t.rb +37 -0
  63. data/lib/y_petri/simulation/transition_representation/tS.rb +38 -0
  64. data/lib/y_petri/simulation/transition_representation/ts.rb +32 -0
  65. data/lib/y_petri/simulation/transition_representation/types.rb +62 -0
  66. data/lib/y_petri/simulation/transition_representation.rb +79 -0
  67. data/lib/y_petri/simulation/transitions/A.rb +40 -0
  68. data/lib/y_petri/simulation/transitions/S.rb +24 -0
  69. data/lib/y_petri/simulation/transitions/T.rb +34 -0
  70. data/lib/y_petri/simulation/transitions/TS.rb +57 -0
  71. data/lib/y_petri/simulation/transitions/Ts.rb +60 -0
  72. data/lib/y_petri/simulation/transitions/a.rb +8 -0
  73. data/lib/y_petri/simulation/transitions/access.rb +186 -0
  74. data/lib/y_petri/simulation/transitions/s.rb +9 -0
  75. data/lib/y_petri/simulation/transitions/t.rb +22 -0
  76. data/lib/y_petri/simulation/transitions/tS.rb +55 -0
  77. data/lib/y_petri/simulation/transitions/ts.rb +58 -0
  78. data/lib/y_petri/simulation/transitions/types.rb +98 -0
  79. data/lib/y_petri/simulation/transitions.rb +21 -0
  80. data/lib/y_petri/simulation.rb +176 -781
  81. data/lib/y_petri/transition/assignment.rb +7 -5
  82. data/lib/y_petri/transition/construction.rb +119 -187
  83. data/lib/y_petri/transition/init.rb +311 -0
  84. data/lib/y_petri/transition/ordinary_timeless.rb +8 -6
  85. data/lib/y_petri/transition/timed.rb +11 -18
  86. data/lib/y_petri/transition.rb +104 -132
  87. data/lib/y_petri/version.rb +1 -1
  88. data/lib/y_petri/world/dependency.rb +40 -0
  89. data/lib/y_petri/world/petri_net_related.rb +61 -0
  90. data/lib/y_petri/{workspace/simulation_related_methods.rb → world/simulation_related.rb} +42 -49
  91. data/lib/y_petri/world.rb +27 -0
  92. data/lib/y_petri.rb +47 -99
  93. data/test/{manipulator_test.rb → agent_test.rb} +19 -17
  94. data/{lib/y_petri → test/examples}/demonstrator.rb +0 -0
  95. data/{lib/y_petri → test/examples}/demonstrator_2.rb +1 -0
  96. data/{lib/y_petri → test/examples}/demonstrator_3.rb +0 -0
  97. data/{lib/y_petri → test/examples}/demonstrator_4.rb +0 -0
  98. data/test/examples/example_2.rb +16 -0
  99. data/test/{manual_examples.rb → examples/manual_examples.rb} +0 -0
  100. data/test/net_test.rb +126 -121
  101. data/test/place_test.rb +1 -1
  102. data/test/sim_test +565 -0
  103. data/test/simulation_test.rb +338 -264
  104. data/test/transition_test.rb +77 -174
  105. data/test/world_mock.rb +12 -0
  106. data/test/{workspace_test.rb → world_test.rb} +19 -20
  107. data/test/y_petri_test.rb +4 -5
  108. metadata +101 -26
  109. data/lib/y_petri/dependency_injection.rb +0 -45
  110. data/lib/y_petri/manipulator/petri_net_related_methods.rb +0 -74
  111. data/lib/y_petri/manipulator.rb +0 -20
  112. data/lib/y_petri/net/selections.rb +0 -209
  113. data/lib/y_petri/simulation/collections.rb +0 -460
  114. data/lib/y_petri/workspace/parametrized_subclassing.rb +0 -22
  115. data/lib/y_petri/workspace/petri_net_related_methods.rb +0 -88
  116. data/lib/y_petri/workspace.rb +0 -16
  117. data/test/timed_simulation_test.rb +0 -153
data/test/sim_test ADDED
@@ -0,0 +1,565 @@
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
+ require_relative 'workspace_mock'
10
+
11
+ describe YPetri::Simulation::TransitionRepresentation do
12
+ before do
13
+ @pç, @tç, @nç = WORKSPACE_MOCK.()
14
+ # Set up places:
15
+ @p1 = @pç.nw "P1", 1
16
+ @p2 = @pç.nw "P2", 2
17
+ @p3 = @pç.nw "P3", 3
18
+ @p4 = @pç.nw "P4", 4
19
+ @p5 = @pç.nw "P5", 5
20
+ # Set up transitions:
21
+ @t1 = @tç.nw "T1", s: { @p1 => -1, @p2 => -1, @p4 => 1 },
22
+ rate: 0.1
23
+ @t2 = @tç.nw "T2", s: { @p1 => -1, @p3 => 1 },
24
+ rate: -> a { a * 0.5 }
25
+ @t3 = @tç.nw "T3", s: { @p1 => -1, @p2 => -1, @p4 => 1 },
26
+ domain: @p3,
27
+ rate: -> a { a * 0.5 }
28
+ @net = @nç.new << @p1 << @p2 << @p3 << @p4 << @p5
29
+ @net.include_transition! @t1
30
+ @net.include_transition! @t2
31
+ @net << @t3
32
+ @s = YPetri::Simulation.new net: @net,
33
+ marking_clamps: { @p1 => 2.0, @p5 => 2.0 },
34
+ initial_marking: { @p2 => @p2.default_marking,
35
+ @p3 => @p3.default_marking,
36
+ @p4 => @p4.default_marking }
37
+ end
38
+
39
+ it "exposes the net" do
40
+ @s.net.must_equal @net
41
+ @s.net.places.size.must_equal 5
42
+ @s.net.transitions.size.must_equal 3
43
+ assert @net.include? @t1
44
+ assert @s.net.include? @t1
45
+ assert @net.include? @t2
46
+ assert @s.net.include? @t2
47
+ assert @net.include? @t3
48
+ assert @s.net.include? @t3
49
+ @s.net.transitions.size.must_equal 3
50
+ end
51
+
52
+ it "exposes Petri net places" do
53
+ @s.places.map( &:source ).must_equal [ @p1, @p2, @p3, @p4, @p5 ]
54
+ @s.pn.must_equal [ :P1, :P2, :P3, :P4, :P5 ]
55
+ end
56
+
57
+ it "exposes Petri net transitions" do
58
+ @s.transitions.map( &:source ).must_equal [ @t1, @t2, @t3 ]
59
+ @s.tn.must_equal [ :T1, :T2, :T3 ]
60
+ end
61
+
62
+ it "exposes place clamps" do
63
+ @s.marking_clamps.values.must_equal [2, 2]
64
+ @s.n_clamped.must_equal [:P1, :P5]
65
+ end
66
+
67
+ it "presents free places" do
68
+ @s.free_places.map( &:source ).must_equal [ @p2, @p3, @p4 ]
69
+ @s.n_free.must_equal [ :P2, :P3, :P4 ]
70
+ end
71
+
72
+ it "presents clamped places" do
73
+ @s.n_clamped.must_equal [ :P1, :P5 ]
74
+ @s.clamped_places.map( &:source ).must_equal [ @p1, @p5 ]
75
+ end
76
+
77
+ it "exposes initial marking" do
78
+ ( @s.free_places.map( &:source ) >> @s.im( *@s.free_places ) )
79
+ .must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
80
+ ( @s.n_free >> @s.im( *@s.free_places ) )
81
+ .must_equal( { P2: 2, P3: 3, P4: 4 } )
82
+ @s.im.must_equal [ 2, 3, 4 ]
83
+ @s.im_vector.must_equal Matrix[[2], [3], [4]]
84
+ @s.im_vector.must_equal @s.iᴍ
85
+ end
86
+
87
+ it "exposes marking (simulation state)" do
88
+ @s.marking.must_equal [2, 3, 4] # (we're after reset)
89
+ @s.free_places( :m ).must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
90
+ @s.free_pp( :m ).must_equal( { P2: 2, P3: 3, P4: 4 } )
91
+ @s.ᴍ.must_equal Matrix[[2], [3], [4]]
92
+ end
93
+
94
+ it "separately exposes marking of clamped places" do
95
+ @s.m( *@s.clamped_places ).must_equal [ 2, 2 ]
96
+ @s.clamped_places( :m_clamped ).must_equal( { @p1 => 2, @p5 => 2 } )
97
+ @s.clamped_pp( :m_clamped ).must_equal( { P1: 2, P5: 2 } )
98
+ @s.ᴍ_clamped.must_equal Matrix[[2], [2]]
99
+ end
100
+
101
+ it "exposes marking of all places (with capitalized M)" do
102
+ @s.pn.must_equal [:P1, :P2, :P3, :P4, :P5]
103
+ @s.m.must_equal [ 2, 2, 3, 4, 2 ]
104
+ ( @s.places >> @s.m( *@s.places ) )
105
+ .must_equal( { @p1 => 2, @p2 => 2, @p3 => 3, @p4 => 4, @p5 => 2 } )
106
+ @s.marking_vector.must_equal Matrix[[2], [2], [3], [4], [2]]
107
+ end
108
+
109
+ it "has stoichiometry matrix for 3. tS transitions" do
110
+ @s.tS_stoichiometry_matrix.must_equal Matrix.empty( 3, 0 )
111
+ @s.tS_SM.must_equal Matrix.empty( 3, 0 )
112
+ end
113
+
114
+ it "has stoichiometry matrix for 6. TS transitions" do
115
+ @s.TS_SM.must_equal Matrix[[-1, 0, -1], [0, 1, 0], [1, 0, 1]]
116
+ @s.SM.must_equal @s.TS_SM
117
+ end
118
+
119
+ it "presents 1. TS transitions" do
120
+ assert_equal [@t1, @t2, @t3], @s.TS_transitions.map( &:source )
121
+ assert_equal( { @t1 => :T1, @t2 => :T2, @t3 => :T3 },
122
+ @s.TS_transitions.map( &:source ) >> @s.n_TS )
123
+ assert_equal [:T1, :T2, :T3], @s.n_TS
124
+ end
125
+
126
+ it "presents 2. Ts transitions" do
127
+ assert_equal [], @s.Ts_transitions
128
+ assert_equal [], @s.n_Ts
129
+ end
130
+
131
+ it "presents 3. tS transitions" do
132
+ assert_equal [], @s.tS_transitions
133
+ assert_equal [], @s.n_tS
134
+ end
135
+
136
+ it "presents 4. ts transitions" do
137
+ assert_equal [], @s.ts_transitions
138
+ assert_equal [], @s.n_ts
139
+ end
140
+
141
+ it "presents A transitions" do
142
+ assert_equal [], @s.A_transitions
143
+ assert_equal [], @s.n_A
144
+ end
145
+
146
+ it "presents S transitions" do
147
+ assert_equal [@t1, @t2, @t3], @s.S_transitions.map( &:source )
148
+ assert_equal [:T1, :T2, :T3], @s.n_S
149
+ end
150
+
151
+ it "presents s transitions" do
152
+ assert_equal [], @s.s_transitions
153
+ assert_equal [], @s.n_s
154
+ end
155
+
156
+ it "1. handles TS transitions" do
157
+ @s.transitions.TS.rate_closures.size.must_equal 3
158
+ @s.transitions.TS.flux_vector.must_equal Matrix.column_vector( [ 0.4, 1.0, 1.5 ] )
159
+ @s.φ_for_SR.must_equal @s.flux_vector
160
+ @s.SR_tt( :φ_for_SR ).must_equal( { T1: 0.4, T2: 1.0, T3: 1.5 } )
161
+ @s.first_order_action_vector_for_SR( 1 )
162
+ .must_equal Matrix.column_vector [ 0.4, 1.0, 1.5 ]
163
+ @s.SR_tt( :first_order_action_for_SR, 1 ).must_equal( T1: 0.4, T2: 1.0, T3: 1.5 )
164
+ @s.Δ_SR( 1 ).must_equal Matrix[[-1.9], [1.0], [1.9]]
165
+ @s.free_pp( :Δ_SR, 1 ).must_equal( { P2: -1.9, P3: 1.0, P4: 1.9 } )
166
+ end
167
+
168
+ it "2. handles Ts transitions" do
169
+ assert_equal [], @s.transitions.Ts.gradient_closures
170
+ @s.transitions.Ts.delta( 1.0 ).must_equal Matrix.zero( @s.n_free.size, 1 )
171
+ end
172
+
173
+ it "3. handles tS transitions" do
174
+ @s.transitions.tS.firing_closures.must_equal []
175
+ @s.transitions.tS.firing_vector.must_equal Matrix.column_vector( [] )
176
+ @s.transitions.tS.delta.must_equal Matrix.zero( @s.n_free.size, 1 )
177
+ end
178
+
179
+ it "1. handles ts transitions" do
180
+ @s.transitions.ts.delta_closures.must_equal []
181
+ end
182
+
183
+ it "presents sparse stoichiometry vectors for its transitions" do
184
+ @s.transition( @t1 ).sparse_sv.must_equal Matrix.cv( [-1, 0, 1] )
185
+ @s.sparse_stoichiometry_vector( of: @t1 )
186
+ .must_equal Matrix.cv( [-1, -1, 0, 1, 0] )
187
+ end
188
+
189
+ it "presents correspondence matrices free, clamped => all places" do
190
+ @s.f2a.must_equal Matrix[[0, 0, 0], [1, 0, 0], [0, 1, 0],
191
+ [0, 0, 1], [0, 0, 0]]
192
+ @s.c2a.must_equal Matrix[[1, 0], [0, 0], [0, 0], [0, 0], [0, 1]]
193
+ end
194
+ end
195
+
196
+ describe ::YPetri::Simulation do
197
+ before do
198
+ @pç, @tç, @nç = WORKSPACE_MOCK.()
199
+ # Set up places:
200
+ @p1 = @pç.nw "P1", 1
201
+ @p2 = @pç.nw "P2", 2
202
+ @p3 = @pç.nw "P3", 3
203
+ @p4 = @pç.nw "P4", 4
204
+ @p5 = @pç.nw "P5", 5
205
+ # Set up transitions:
206
+ @t1 = @tç.nw "T1", s: { @p1 => -1, @p2 => -1, @p4 => 1 },
207
+ rate: 0.1
208
+ @t2 = @tç.nw "T2", s: { @p1 => -1, @p3 => 1 },
209
+ rate: -> a { a * 0.5 }
210
+ @t3 = @tç.new "T3", s: { @p1 => -1, @p2 => -1, @p4 => 1 },
211
+ domain: @p3,
212
+ rate: -> a { a * 0.5 }
213
+ @net = @nç.new << @p1 << @p2 << @p3 << @p4 << @p5
214
+ @net.include_transition! @t1
215
+ @net.include_transition! @t2
216
+ @net << @t3
217
+ @s = YPetri::Simulation.new net: @net,
218
+ marking_clamps: { @p1 => 2.0, @p5 => 2.0 },
219
+ initial_marking: { @p2 => @p2.default_marking,
220
+ @p3 => @p3.default_marking,
221
+ @p4 => @p4.default_marking }
222
+ end
223
+
224
+ it "exposes the net" do
225
+ @s.net.must_equal @net
226
+ @s.net.places.size.must_equal 5
227
+ @s.net.transitions.size.must_equal 3
228
+ assert @net.include? @t1
229
+ assert @s.net.include? @t1
230
+ assert @net.include? @t2
231
+ assert @s.net.include? @t2
232
+ assert @net.include? @t3
233
+ assert @s.net.include? @t3
234
+ @s.net.transitions.size.must_equal 3
235
+ end
236
+
237
+ it "exposes Petri net places" do
238
+ @s.places.map( &:source ).must_equal [ @p1, @p2, @p3, @p4, @p5 ]
239
+ @s.pn.must_equal [ :P1, :P2, :P3, :P4, :P5 ]
240
+ end
241
+
242
+ it "exposes Petri net transitions" do
243
+ @s.transitions.map( &:source ).must_equal [ @t1, @t2, @t3 ]
244
+ @s.tn.must_equal [ :T1, :T2, :T3 ]
245
+ end
246
+
247
+ it "exposes place clamps" do
248
+ @s.marking_clamps.values.must_equal [2, 2]
249
+ @s.n_clamped.must_equal [:P1, :P5]
250
+ end
251
+
252
+ it "presents free places" do
253
+ @s.free_places.map( &:source ).must_equal [ @p2, @p3, @p4 ]
254
+ @s.n_free.must_equal [ :P2, :P3, :P4 ]
255
+ end
256
+
257
+ it "presents clamped places" do
258
+ @s.n_clamped.must_equal [ :P1, :P5 ]
259
+ @s.clamped_places.map( &:source ).must_equal [ @p1, @p5 ]
260
+ end
261
+
262
+ it "exposes initial marking" do
263
+ ( @s.free_places.map( &:source ) >> @s.im( *@s.free_places ) )
264
+ .must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
265
+ ( @s.n_free >> @s.im( *@s.free_places ) )
266
+ .must_equal( { P2: 2, P3: 3, P4: 4 } )
267
+ @s.im.must_equal [ 2, 3, 4 ]
268
+ @s.im_vector.must_equal Matrix[[2], [3], [4]]
269
+ @s.im_vector.must_equal @s.iᴍ
270
+ end
271
+
272
+ it "exposes marking (simulation state)" do
273
+ @s.marking.must_equal [2, 3, 4] # (we're after reset)
274
+ @s.free_places( :m ).must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
275
+ @s.free_pp( :m ).must_equal( { P2: 2, P3: 3, P4: 4 } )
276
+ @s.ᴍ.must_equal Matrix[[2], [3], [4]]
277
+ end
278
+
279
+ it "separately exposes marking of clamped places" do
280
+ @s.m( *@s.clamped_places ).must_equal [ 2, 2 ]
281
+ @s.clamped_places( :m_clamped ).must_equal( { @p1 => 2, @p5 => 2 } )
282
+ @s.clamped_pp( :m_clamped ).must_equal( { P1: 2, P5: 2 } )
283
+ @s.ᴍ_clamped.must_equal Matrix[[2], [2]]
284
+ end
285
+
286
+ it "exposes marking of all places (with capitalized M)" do
287
+ @s.pn.must_equal [:P1, :P2, :P3, :P4, :P5]
288
+ @s.m.must_equal [ 2, 2, 3, 4, 2 ]
289
+ ( @s.places >> @s.m( *@s.places ) )
290
+ .must_equal( { @p1 => 2, @p2 => 2, @p3 => 3, @p4 => 4, @p5 => 2 } )
291
+ @s.marking_vector.must_equal Matrix[[2], [2], [3], [4], [2]]
292
+ end
293
+
294
+ it "has stoichiometry matrix for 3. tS transitions" do
295
+ @s.tS_stoichiometry_matrix.must_equal Matrix.empty( 3, 0 )
296
+ @s.tS_SM.must_equal Matrix.empty( 3, 0 )
297
+ end
298
+
299
+ it "has stoichiometry matrix for 6. TS transitions" do
300
+ @s.TS_SM.must_equal Matrix[[-1, 0, -1], [0, 1, 0], [1, 0, 1]]
301
+ @s.SM.must_equal @s.TS_SM
302
+ end
303
+
304
+ it "presents 1. TS transitions" do
305
+ assert_equal [@t1, @t2, @t3], @s.TS_transitions.map( &:source )
306
+ assert_equal( { @t1 => :T1, @t2 => :T2, @t3 => :T3 },
307
+ @s.TS_transitions.map( &:source ) >> @s.n_TS )
308
+ assert_equal [:T1, :T2, :T3], @s.n_TS
309
+ end
310
+
311
+ it "presents 2. Ts transitions" do
312
+ assert_equal [], @s.Ts_transitions
313
+ assert_equal [], @s.n_Ts
314
+ end
315
+
316
+ it "presents 3. tS transitions" do
317
+ assert_equal [], @s.tS_transitions
318
+ assert_equal [], @s.n_tS
319
+ end
320
+
321
+ it "presents 4. ts transitions" do
322
+ assert_equal [], @s.ts_transitions
323
+ assert_equal [], @s.n_ts
324
+ end
325
+
326
+ it "presents A transitions" do
327
+ assert_equal [], @s.A_transitions
328
+ assert_equal [], @s.n_A
329
+ end
330
+
331
+ it "presents S transitions" do
332
+ assert_equal [@t1, @t2, @t3], @s.S_transitions.map( &:source )
333
+ assert_equal [:T1, :T2, :T3], @s.n_S
334
+ end
335
+
336
+ it "presents s transitions" do
337
+ assert_equal [], @s.s_transitions
338
+ assert_equal [], @s.n_s
339
+ end
340
+
341
+ it "1. handles TS transitions" do
342
+ @s.transitions.TS.rate_closures.size.must_equal 3
343
+ @s.transitions.TS.flux_vector.must_equal Matrix.column_vector( [ 0.4, 1.0, 1.5 ] )
344
+ @s.φ_for_SR.must_equal @s.flux_vector
345
+ @s.SR_tt( :φ_for_SR ).must_equal( { T1: 0.4, T2: 1.0, T3: 1.5 } )
346
+ @s.first_order_action_vector_for_SR( 1 )
347
+ .must_equal Matrix.column_vector [ 0.4, 1.0, 1.5 ]
348
+ @s.SR_tt( :first_order_action_for_SR, 1 ).must_equal( T1: 0.4, T2: 1.0, T3: 1.5 )
349
+ @s.Δ_SR( 1 ).must_equal Matrix[[-1.9], [1.0], [1.9]]
350
+ @s.free_pp( :Δ_SR, 1 ).must_equal( { P2: -1.9, P3: 1.0, P4: 1.9 } )
351
+ end
352
+
353
+ it "2. handles Ts transitions" do
354
+ assert_equal [], @s.transitions.Ts.gradient_closures
355
+ @s.transitions.Ts.delta( 1.0 ).must_equal Matrix.zero( @s.n_free.size, 1 )
356
+ end
357
+
358
+ it "3. handles tS transitions" do
359
+ @s.transitions.tS.firing_closures.must_equal []
360
+ @s.transitions.tS.firing_vector.must_equal Matrix.column_vector( [] )
361
+ @s.transitions.tS.delta.must_equal Matrix.zero( @s.n_free.size, 1 )
362
+ end
363
+
364
+ it "1. handles ts transitions" do
365
+ @s.transitions.ts.delta_closures.must_equal []
366
+ end
367
+
368
+ it "presents sparse stoichiometry vectors for its transitions" do
369
+ @s.transition( @t1 ).sparse_sv.must_equal Matrix.cv( [-1, 0, 1] )
370
+ @s.sparse_stoichiometry_vector( of: @t1 )
371
+ .must_equal Matrix.cv( [-1, -1, 0, 1, 0] )
372
+ end
373
+
374
+ it "presents correspondence matrices free, clamped => all places" do
375
+ @s.f2a.must_equal Matrix[[0, 0, 0], [1, 0, 0], [0, 1, 0],
376
+ [0, 0, 1], [0, 0, 0]]
377
+ @s.c2a.must_equal Matrix[[1, 0], [0, 0], [0, 0], [0, 0], [0, 1]]
378
+ end
379
+ end
380
+
381
+
382
+ describe ::YPetri::Simulation do
383
+ before do
384
+ @pç, @tç, @nç = WORKSPACE_MOCK.()
385
+ # Set up places:
386
+ @p1 = @pç.nw "P1", 1
387
+ @p2 = @pç.nw "P2", 2
388
+ @p3 = @pç.nw "P3", 3
389
+ @p4 = @pç.nw "P4", 4
390
+ @p5 = @pç.nw "P5", 5
391
+ # Set up transitions:
392
+ @t1 = @tç.nw "T1", s: { @p1 => -1, @p2 => -1, @p4 => 1 },
393
+ rate: 0.1
394
+ @t2 = @tç.nw "T2", s: { @p1 => -1, @p3 => 1 },
395
+ rate: -> a { a * 0.5 }
396
+ @t3 = @tç.new "T3", s: { @p1 => -1, @p2 => -1, @p4 => 1 },
397
+ domain: @p3,
398
+ rate: -> a { a * 0.5 }
399
+ @net = @nç.new << @p1 << @p2 << @p3 << @p4 << @p5
400
+ @net.include_transition! @t1
401
+ @net.include_transition! @t2
402
+ @net << @t3
403
+ @s = YPetri::Simulation.new net: @net,
404
+ marking_clamps: { @p1 => 2.0, @p5 => 2.0 },
405
+ initial_marking: { @p2 => @p2.default_marking,
406
+ @p3 => @p3.default_marking,
407
+ @p4 => @p4.default_marking }
408
+ end
409
+
410
+ it "exposes the net" do
411
+ @s.net.must_equal @net
412
+ @s.net.places.size.must_equal 5
413
+ @s.net.transitions.size.must_equal 3
414
+ assert @net.include? @t1
415
+ assert @s.net.include? @t1
416
+ assert @net.include? @t2
417
+ assert @s.net.include? @t2
418
+ assert @net.include? @t3
419
+ assert @s.net.include? @t3
420
+ @s.net.transitions.size.must_equal 3
421
+ end
422
+
423
+ it "exposes Petri net places" do
424
+ @s.places.map( &:source ).must_equal [ @p1, @p2, @p3, @p4, @p5 ]
425
+ @s.pn.must_equal [ :P1, :P2, :P3, :P4, :P5 ]
426
+ end
427
+
428
+ it "exposes Petri net transitions" do
429
+ @s.transitions.map( &:source ).must_equal [ @t1, @t2, @t3 ]
430
+ @s.tn.must_equal [ :T1, :T2, :T3 ]
431
+ end
432
+
433
+ it "exposes place clamps" do
434
+ @s.marking_clamps.values.must_equal [2, 2]
435
+ @s.n_clamped.must_equal [:P1, :P5]
436
+ end
437
+
438
+ it "presents free places" do
439
+ @s.free_places.map( &:source ).must_equal [ @p2, @p3, @p4 ]
440
+ @s.n_free.must_equal [ :P2, :P3, :P4 ]
441
+ end
442
+
443
+ it "presents clamped places" do
444
+ @s.n_clamped.must_equal [ :P1, :P5 ]
445
+ @s.clamped_places.map( &:source ).must_equal [ @p1, @p5 ]
446
+ end
447
+
448
+ it "exposes initial marking" do
449
+ ( @s.free_places.map( &:source ) >> @s.im( *@s.free_places ) )
450
+ .must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
451
+ ( @s.n_free >> @s.im( *@s.free_places ) )
452
+ .must_equal( { P2: 2, P3: 3, P4: 4 } )
453
+ @s.im.must_equal [ 2, 3, 4 ]
454
+ @s.im_vector.must_equal Matrix[[2], [3], [4]]
455
+ @s.im_vector.must_equal @s.iᴍ
456
+ end
457
+
458
+ it "exposes marking (simulation state)" do
459
+ @s.marking.must_equal [2, 3, 4] # (we're after reset)
460
+ @s.free_places( :m ).must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
461
+ @s.free_pp( :m ).must_equal( { P2: 2, P3: 3, P4: 4 } )
462
+ @s.ᴍ.must_equal Matrix[[2], [3], [4]]
463
+ end
464
+
465
+ it "separately exposes marking of clamped places" do
466
+ @s.m( *@s.clamped_places ).must_equal [ 2, 2 ]
467
+ @s.clamped_places( :m_clamped ).must_equal( { @p1 => 2, @p5 => 2 } )
468
+ @s.clamped_pp( :m_clamped ).must_equal( { P1: 2, P5: 2 } )
469
+ @s.ᴍ_clamped.must_equal Matrix[[2], [2]]
470
+ end
471
+
472
+ it "exposes marking of all places (with capitalized M)" do
473
+ @s.pn.must_equal [:P1, :P2, :P3, :P4, :P5]
474
+ @s.m.must_equal [ 2, 2, 3, 4, 2 ]
475
+ ( @s.places >> @s.m( *@s.places ) )
476
+ .must_equal( { @p1 => 2, @p2 => 2, @p3 => 3, @p4 => 4, @p5 => 2 } )
477
+ @s.marking_vector.must_equal Matrix[[2], [2], [3], [4], [2]]
478
+ end
479
+
480
+ it "has stoichiometry matrix for 3. tS transitions" do
481
+ @s.tS_stoichiometry_matrix.must_equal Matrix.empty( 3, 0 )
482
+ @s.tS_SM.must_equal Matrix.empty( 3, 0 )
483
+ end
484
+
485
+ it "has stoichiometry matrix for 6. TS transitions" do
486
+ @s.TS_SM.must_equal Matrix[[-1, 0, -1], [0, 1, 0], [1, 0, 1]]
487
+ @s.SM.must_equal @s.TS_SM
488
+ end
489
+
490
+ it "presents 1. TS transitions" do
491
+ assert_equal [@t1, @t2, @t3], @s.TS_transitions.map( &:source )
492
+ assert_equal( { @t1 => :T1, @t2 => :T2, @t3 => :T3 },
493
+ @s.TS_transitions.map( &:source ) >> @s.n_TS )
494
+ assert_equal [:T1, :T2, :T3], @s.n_TS
495
+ end
496
+
497
+ it "presents 2. Ts transitions" do
498
+ assert_equal [], @s.Ts_transitions
499
+ assert_equal [], @s.n_Ts
500
+ end
501
+
502
+ it "presents 3. tS transitions" do
503
+ assert_equal [], @s.tS_transitions
504
+ assert_equal [], @s.n_tS
505
+ end
506
+
507
+ it "presents 4. ts transitions" do
508
+ assert_equal [], @s.ts_transitions
509
+ assert_equal [], @s.n_ts
510
+ end
511
+
512
+ it "presents A transitions" do
513
+ assert_equal [], @s.A_transitions
514
+ assert_equal [], @s.n_A
515
+ end
516
+
517
+ it "presents S transitions" do
518
+ assert_equal [@t1, @t2, @t3], @s.S_transitions.map( &:source )
519
+ assert_equal [:T1, :T2, :T3], @s.n_S
520
+ end
521
+
522
+ it "presents s transitions" do
523
+ assert_equal [], @s.s_transitions
524
+ assert_equal [], @s.n_s
525
+ end
526
+
527
+ it "1. handles TS transitions" do
528
+ @s.transitions.TS.rate_closures.size.must_equal 3
529
+ @s.transitions.TS.flux_vector.must_equal Matrix.column_vector( [ 0.4, 1.0, 1.5 ] )
530
+ @s.φ_for_SR.must_equal @s.flux_vector
531
+ @s.SR_tt( :φ_for_SR ).must_equal( { T1: 0.4, T2: 1.0, T3: 1.5 } )
532
+ @s.first_order_action_vector_for_SR( 1 )
533
+ .must_equal Matrix.column_vector [ 0.4, 1.0, 1.5 ]
534
+ @s.SR_tt( :first_order_action_for_SR, 1 ).must_equal( T1: 0.4, T2: 1.0, T3: 1.5 )
535
+ @s.Δ_SR( 1 ).must_equal Matrix[[-1.9], [1.0], [1.9]]
536
+ @s.free_pp( :Δ_SR, 1 ).must_equal( { P2: -1.9, P3: 1.0, P4: 1.9 } )
537
+ end
538
+
539
+ it "2. handles Ts transitions" do
540
+ assert_equal [], @s.transitions.Ts.gradient_closures
541
+ @s.transitions.Ts.delta( 1.0 ).must_equal Matrix.zero( @s.n_free.size, 1 )
542
+ end
543
+
544
+ it "3. handles tS transitions" do
545
+ @s.transitions.tS.firing_closures.must_equal []
546
+ @s.transitions.tS.firing_vector.must_equal Matrix.column_vector( [] )
547
+ @s.transitions.tS.delta.must_equal Matrix.zero( @s.n_free.size, 1 )
548
+ end
549
+
550
+ it "1. handles ts transitions" do
551
+ @s.transitions.ts.delta_closures.must_equal []
552
+ end
553
+
554
+ it "presents sparse stoichiometry vectors for its transitions" do
555
+ @s.transition( @t1 ).sparse_sv.must_equal Matrix.cv( [-1, 0, 1] )
556
+ @s.sparse_stoichiometry_vector( of: @t1 )
557
+ .must_equal Matrix.cv( [-1, -1, 0, 1, 0] )
558
+ end
559
+
560
+ it "presents correspondence matrices free, clamped => all places" do
561
+ @s.f2a.must_equal Matrix[[0, 0, 0], [1, 0, 0], [0, 1, 0],
562
+ [0, 0, 1], [0, 0, 0]]
563
+ @s.c2a.must_equal Matrix[[1, 0], [0, 0], [0, 0], [0, 0], [0, 1]]
564
+ end
565
+ end