y_petri 2.0.15 → 2.1.3

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.
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