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
@@ -1,5 +1,5 @@
1
1
  #! /usr/bin/ruby
2
- # -*- coding: utf-8 -*-
2
+ # encoding: utf-8
3
3
 
4
4
  require 'minitest/spec'
5
5
  require 'minitest/autorun'
@@ -7,275 +7,349 @@ require_relative '../lib/y_petri' # tested component itself
7
7
  # require 'y_petri'
8
8
  # require 'sy'
9
9
 
10
- describe ::YPetri::Simulation do
10
+ describe YPetri::Simulation do
11
11
  before do
12
- @ = 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!
17
- klass.class_exec {
18
- private
19
- define_method :Place do pç end
20
- define_method :Transition do tç end
21
- define_method :Net do nç end
22
- }
23
- }
24
- @p1 = @pç.new name: "P1", default_marking: 1
25
- @p2 = @pç.new name: "P2", default_marking: 2
26
- @p3 = @pç.new name: "P3", default_marking: 3
27
- @p4 = @pç.new name: "P4", default_marking: 4
28
- @p5 = @pç.new name: "P5", default_marking: 5
29
- @t1 = @tç.new name: "T1",
30
- s: { @p1 => -1, @p2 => -1, @p4 => 1 },
31
- rate: 0.1
32
- @t2 = @tç.new name: "T2",
33
- s: { @p1 => -1, @p3 => 1 },
34
- rate: -> a { a * 0.5 }
35
- @t3 = @tç.new name: "T3",
36
- s: { @p1 => -1, @p2 => -1, @p4 => 1 },
37
- domain: @p3,
38
- rate: -> a { a * 0.5 }
39
- @net = @nç.new << @p1 << @p2 << @p3 << @p4 << @p5
40
- @net.include_transition! @t1
41
- @net.include_transition! @t2
42
- @net << @t3
43
- @s = YPetri::Simulation.new net: @net,
44
- marking_clamps: { @p1 => 2.0, @p5 => 2.0 },
45
- initial_marking: { @p2 => @p2.default_marking,
46
- @p3 => @p3.default_marking,
47
- @p4 => @p4.default_marking }
48
- end
49
-
50
- it "exposes the net" do
51
- @s.net.must_equal @net
52
- @s.net.places.size.must_equal 5
53
- @s.net.transitions.size.must_equal 3
54
- assert @net.include? @t1
55
- assert @s.net.include? @t1
56
- assert @net.include? @t2
57
- assert @s.net.include? @t2
58
- assert @net.include? @t3
59
- assert @s.net.include? @t3
60
- @s.net.transitions.size.must_equal 3
61
- end
62
-
63
- it "exposes Petri net places" do
64
- @s.places.must_equal [ @p1, @p2, @p3, @p4, @p5 ]
65
- @s.pp.must_equal [ :P1, :P2, :P3, :P4, :P5 ]
66
- @s.places( :pp ).must_equal( { @p1 => :P1, @p2 => :P2, @p3 => :P3,
67
- @p4 => :P4, @p5 => :P5 } )
68
- @s.pp( :pp ).must_equal( { P1: :P1, P2: :P2, P3: :P3, P4: :P4, P5: :P5 } )
69
- end
70
-
71
- it "exposes Petri net transitions" do
72
- @s.transitions.must_equal [ @t1, @t2, @t3 ]
73
- @s.tt.must_equal [ :T1, :T2, :T3 ]
74
- @s.transitions( :tt ).must_equal( { @t1 => :T1, @t2 => :T2, @t3 => :T3 } )
75
- @s.tt( :tt ).must_equal( { T1: :T1, T2: :T2, T3: :T3 } )
76
- end
77
-
78
- it "exposes place clamps" do
79
- @s.clamped_places( :place_clamps ).must_equal( { @p1 => 2, @p5 => 2 } )
80
- @s.clamped_pp( :place_clamps ).must_equal( { P1: 2, P5: 2 } )
81
- end
82
-
83
- it "presents free places" do
84
- @s.free_places.must_equal [ @p2, @p3, @p4 ]
85
- @s.free_pp.must_equal [ :P2, :P3, :P4 ]
86
- @s.free_places( :free_pp )
87
- .must_equal( { @p2 => :P2, @p3 => :P3, @p4 => :P4 } )
88
- @s.free_pp( :free_pp )
89
- .must_equal( { P2: :P2, P3: :P3, P4: :P4 } )
90
- end
91
-
92
- it "presents clamped places" do
93
- @s.clamped_places.must_equal [ @p1, @p5 ]
94
- @s.clamped_pp.must_equal [ :P1, :P5 ]
95
- @s.clamped_places( :clamped_pp ).must_equal( { @p1 => :P1, @p5 => :P5 } )
96
- @s.clamped_pp( :clamped_pp ).must_equal( { P1: :P1, P5: :P5 } )
97
- end
98
-
99
- it "exposes initial marking" do
100
- @s.free_places( :im ).must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
101
- @s.free_pp( :im ).must_equal( { P2: 2, P3: 3, P4: 4 } )
102
- @s.im.must_equal [ 2, 3, 4 ]
103
- @s.im_vector.must_equal Matrix[[2], [3], [4]]
104
- @s.im_vector.must_equal @s.iᴍ
105
- end
106
-
107
- it "exposes marking (simulation state)" do
108
- @s.m.must_equal [2, 3, 4] # (we're after reset)
109
- @s.free_places( :m ).must_equal( { @p2 => 2, @p3 => 3, @p4 => 4 } )
110
- @s.free_pp( :m ).must_equal( { P2: 2, P3: 3, P4: 4 } )
111
- @s.ᴍ.must_equal Matrix[[2], [3], [4]]
112
- end
113
-
114
- it "separately exposes marking of clamped places" do
115
- @s.m_clamped.must_equal [ 2, 2 ]
116
- @s.clamped_places( :m_clamped ).must_equal( { @p1 => 2, @p5 => 2 } )
117
- @s.clamped_pp( :m_clamped ).must_equal( { P1: 2, P5: 2 } )
118
- @s.ᴍ_clamped.must_equal Matrix[[2], [2]]
119
- end
120
-
121
- it "exposes marking of all places (with capitalized M)" do
122
- @s.marking.must_equal [ 2, 2, 3, 4, 2 ]
123
- @s.places( :marking )
124
- .must_equal( { @p1 => 2, @p2 => 2, @p3 => 3, @p4 => 4, @p5 => 2 } )
125
- @s.pp( :marking ).must_equal( { P1: 2, P2: 2, P3: 3, P4: 4, P5: 2 } )
126
- @s.marking_vector.must_equal Matrix[[2], [2], [3], [4], [2]]
127
- end
128
-
129
- it "has #S_for / #stoichiometry_matrix_for" do
130
- assert_equal Matrix.empty(3, 0), @s.S_for( [] )
131
- assert_equal Matrix[[-1], [0], [1]], @s.S_for( [@t1] )
132
- x = Matrix[[-1, -1], [0, 0], [1, 1]]
133
- x.must_equal @s.S_for( [@t1, @t3] )
134
- x.must_equal( @s.S_for( [@t1, @t3] ) )
135
- @s.stoichiometry_matrix_for( [] ).must_equal Matrix.empty( 5, 0 )
136
- end
137
-
138
- it "has stoichiometry matrix for 3. tS transitions" do
139
- @s.S_tS.must_equal Matrix.empty( 3, 0 )
140
- end
141
-
142
- it "has stoichiometry matrix for 4. Sr transitions" do
143
- @s.S_TSr.must_equal Matrix.empty( 3, 0 )
144
- end
145
-
146
- it "has stoichiometry matrix for 6. SR transitions" do
147
- @s.S_SR.must_equal Matrix[[-1, 0, -1], [0, 1, 0], [1, 0, 1]]
148
- @s.S.must_equal @s.S_SR
149
- end
150
-
151
- it "presents 1. ts" do
152
- assert_equal [], @s.ts_transitions
153
- assert_equal( {}, @s.ts_transitions( :ts_transitions ) )
154
- assert_equal [], @s.ts_tt
155
- assert_equal( {}, @s.ts_tt( :ts_tt ) )
156
- end
157
-
158
- it "presents 2. tS transitions" do
159
- assert_equal [], @s.tS_transitions
160
- assert_equal( {}, @s.tS_transitions( :tS_transitions ) )
161
- assert_equal [], @s.tS_tt
162
- assert_equal( {}, @s.tS_tt( :tS_tt ) )
163
- end
164
-
165
- it "presents 3. Tsr transitions" do
166
- assert_equal [], @s.Tsr_transitions
167
- assert_equal( {}, @s.Tsr_transitions( :Tsr_transitions ) )
168
- assert_equal [], @s.Tsr_tt
169
- assert_equal( {}, @s.Tsr_tt( :Tsr_tt ) )
170
- end
171
-
172
- it "presents 4. TSr transitions" do
173
- assert_equal [], @s.TSr_transitions
174
- assert_equal( {}, @s.TSr_transitions( :TSr_tt ) )
175
- assert_equal [], @s.TSr_tt
176
- assert_equal( {}, @s.TSr_tt( :TSr_tt ) )
177
- end
178
-
179
- it "presents 5. sR transitions" do
180
- assert_equal [], @s.sR_transitions
181
- assert_equal( {}, @s.sR_transitions( :sR_transitions ) )
182
- assert_equal [], @s.sR_tt
183
- assert_equal( {}, @s.sR_tt( :sR_tt ) )
184
- end
185
-
186
- it "presents SR transitions" do
187
- assert_equal [@t1, @t2, @t3], @s.SR_transitions
188
- assert_equal( { @t1 => :T1, @t2 => :T2, @t3 => :T3 },
189
- @s.SR_transitions( :SR_tt ) )
190
- assert_equal [:T1, :T2, :T3], @s.SR_tt
191
- assert_equal( { T1: :T1, T2: :T2, T3: :T3 }, @s.SR_tt( :SR_tt ) )
192
- end
193
-
194
- it "presents A transitions" do
195
- assert_equal [], @s.A_transitions
196
- assert_equal( {}, @s.A_transitions( :A_tt ) )
197
- assert_equal [], @s.A_tt
198
- assert_equal( {}, @s.A_tt( :A_tt ) )
199
- end
200
-
201
- it "presents S transitions" do
202
- assert_equal [@t1, @t2, @t3], @s.S_transitions
203
- assert_equal [:T1, :T2, :T3], @s.S_tt
204
- assert_equal( { T1: :T1, T2: :T2, T3: :T3 }, @s.S_tt( :S_tt ) )
205
- end
206
-
207
- it "presents s transitions" do
208
- assert_equal [], @s.s_transitions
209
- assert_equal [], @s.s_tt
210
- assert_equal( {}, @s.s_tt( :s_tt ) )
211
- end
212
-
213
- it "presents R transitions" do
214
- assert_equal [@t1, @t2, @t3], @s.R_transitions
215
- assert_equal [:T1, :T2, :T3], @s.R_tt
216
- assert_equal( { T1: :T1, T2: :T2, T3: :T3 }, @s.R_tt( :R_tt ) )
217
- end
218
-
219
- it "presents r transitions" do
220
- assert_equal [], @s.r_transitions
221
- assert_equal [], @s.r_tt
222
- end
223
-
224
- it "1. handles ts transitions" do
225
- @s.Δ_closures_for_tsa.must_equal []
226
- @s.Δ_if_tsa_fire_once.must_equal Matrix.zero( @s.free_pp.size, 1 )
227
- end
228
-
229
- it "2. handles Tsr transitions" do
230
- @s.Δ_closures_for_Tsr.must_equal []
231
- @s.Δ_Tsr( 1.0 ).must_equal Matrix.zero( @s.free_pp.size, 1 )
232
- end
233
-
234
- it "3. handles tS transitions" do
235
- @s.action_closures_for_tS.must_equal []
236
- @s.action_vector_for_tS.must_equal Matrix.column_vector( [] )
237
- @s.ᴀ_t.must_equal Matrix.column_vector( [] )
238
- @s.Δ_if_tS_fire_once.must_equal Matrix.zero( @s.free_pp.size, 1 )
239
- end
240
-
241
- it "4. handles TSr transitions" do
242
- @s.action_closures_for_TSr.must_equal []
243
- @s.action_closures_for_Tr.must_equal []
244
- @s.action_vector_for_TSr( 1.0 ).must_equal Matrix.column_vector( [] )
245
- @s.action_vector_for_Tr( 1.0 ).must_equal Matrix.column_vector( [] )
246
- @s.Δ_TSr( 1.0 ).must_equal Matrix.zero( @s.free_pp.size, 1 )
12
+ @w = YPetri::World.new
13
+ end
14
+
15
+ it "should allow for creation of an empty simulation" do
16
+ net = @w.Net.new
17
+ sim = net.simulation
18
+ sim.pp.must_equal []
19
+ sim.pp( *[] ).must_equal []
20
+ sim.tt.must_equal( [] )
21
+ sim.tt( *[] ).must_equal []
22
+ end
23
+
24
+ describe "simulation setup" do
25
+ before do
26
+ @p = @w.Place.new name: :A, default_marking: 1
27
+ @q = @w.Place.new name: :B, default_marking: 2
28
+ @net = @w.Net.of @p, @q
29
+ end
30
+
31
+ it "should allow to set up a simplistic simulation instance" do
32
+ @net.simulation
33
+ @net.simulation marking_clamps: { @q => 42 } # one clamp
34
+ @net.simulation initial_marking: { @p => 42, @q => 43 }
35
+ @net.simulation marking_clamps: { @p => 42 }, initial_marking: { @q => 43 }
36
+ @net.simulation initial_marking: { A: 42 }
37
+ end
38
+
39
+ it "should fail with malformed arguments" do
40
+ -> { @net.simulation use_default_marking: false }.must_raise TypeError
41
+ -> { @net.simulation initial_marking: { Foo: 1 } }.must_raise NameError
42
+ end
43
+
44
+ describe "place representation aspects" do
45
+ before do
46
+ @s = YPetri::Simulation.new( net: @net,
47
+ initial_marking: { A: 42 },
48
+ marking_clamps: { B: 43 } )
49
+ end
50
+
51
+ it "should have elements/access" do
52
+ @s.send( :place, :A )
53
+ .must_be_kind_of YPetri::Simulation::PlaceRepresentation
54
+ @s.send( :place, :B )
55
+ .must_be_kind_of YPetri::Simulation::PlaceRepresentation
56
+ @s.net.places.names.must_equal [:A, :B]
57
+ @s.pn.must_equal [:A, :B]
58
+ @s.send( :places ).free.size.must_equal 1
59
+ @s.send( :free_places ).names.must_equal [:A]
60
+ @s.send( :places ).clamped.size.must_equal 1
61
+ @s.send( :clamped_places ).names.must_equal [:B]
62
+ @s.send( :places, [:A] ).map( &:source ).must_equal [@p]
63
+ @s.send( :transitions, [] ).must_equal []
64
+ @s.send( :places, [:A] ).map( &:source ).must_equal [@p]
65
+ @s.send( :places, [] ).must_equal []
66
+ end
67
+
68
+ describe "marking vector representation" do
69
+ it "should work" do
70
+ @s.instance_variable_get( :@m_vector ).must_equal @s.m_vector
71
+ @s.m_vector.must_be_kind_of YPetri::Simulation::MarkingVector
72
+ @s.m_vector.size.must_equal 2
73
+ @s.m_vector.to_a.must_equal [42, 43]
74
+ @s.m.must_equal [42, 43]
75
+ @s.marking.must_equal [42]
76
+ @s.marking_clamps.keys_to_names.must_equal( { B: 43 } )
77
+ end
78
+ end
79
+ end # describe simulation step
80
+
81
+ describe "transition representation aspects" do
82
+ before do
83
+ @ts = @w.Transition.new name: "T_ts", codomain: :A, action: -> { 1 }
84
+ @tS = @w.Transition.new name: "T_tS", s: { B: -1, A: 1 }, action: proc { 1 }
85
+ @Ts = @w.Transition.new name: "T_Ts", codomain: :A, rate: -> { 1 }
86
+ @TS = @w.Transition.new name: "T_TS", s: { B: -1, A: 1 }, rate: proc { 1 }
87
+ end
88
+
89
+ it "should be what intended" do
90
+ @ts.type.must_equal :ts
91
+ @ts.domain.must_equal []
92
+ @ts.codomain.must_equal [@p]
93
+ @tS.type.must_equal :tS
94
+ @tS.domain.must_equal [@q] # inferred
95
+ @tS.codomain.must_equal [@q, @p]
96
+ @Ts.type.must_equal :Ts
97
+ @Ts.domain.must_equal []
98
+ @Ts.codomain.must_equal [@p]
99
+ @TS.type.must_equal :TS
100
+ @TS.domain.must_equal [@q] # inferred
101
+ @TS.codomain.must_equal [@q, @p]
102
+ end
103
+
104
+ describe "ts transition" do
105
+ before do
106
+ @net = @w.Net.of @p, @q, @ts
107
+ end
108
+
109
+ describe "no clamps" do
110
+ before do
111
+ @sim = @net.simulation net: @net
112
+ end
113
+
114
+ it "should behave" do
115
+ @sim.tt.size.must_equal 1
116
+ @ts.codomain.names.must_equal [:A]
117
+ @sim.ts_tt.first.codomain.names.must_equal [:A]
118
+ @ts.domain.names.must_equal []
119
+ @sim.ts_tt.first.domain.names.must_equal []
120
+ @sim.timed?.must_equal false
121
+ @sim.m.must_equal [1, 2]
122
+ @sim.pm.must_equal( { A: 1, B: 2 } )
123
+ @sim.recording.must_equal( { 0 => [1, 2]} )
124
+ @sim.simulation_method.must_equal :pseudo_euler
125
+ @sim.core.must_be_kind_of YPetri::Core
126
+ @sim.ts_tt.first.domain.must_equal []
127
+ @sim.send( :ts_transitions ).first.domain_access_code.must_equal ''
128
+ λ = @sim.send( :transitions ).ts.first.delta_closure
129
+ λ.arity.must_equal 0
130
+ λ.call.must_equal 1
131
+ cc = @sim.send( :transitions ).ts.delta_closures
132
+ cc.map( &:call ).must_equal [1]
133
+ cl = @sim.send( :transitions ).ts.delta_closure
134
+ cl.call.must_equal Matrix[ [1], [0] ]
135
+ @sim.step!
136
+ @sim.pm.must_equal( { A: 2, B: 2 } ) # marking of A goes up by 1
137
+ @sim.recording.must_equal( { 0 => [1, 2], 1 => [2, 2] } )
138
+ end
139
+ end
140
+
141
+ describe "with clamps" do
142
+ before do
143
+ @sim = @net.simulation marking_clamps: { B: 42 }
144
+ end
145
+
146
+ it "should behave" do
147
+ @sim.recording.must_equal( { 0 => [1] } )
148
+ @sim.step!
149
+ @sim.recording.must_equal( { 0 => [1], 1 => [2] } )
150
+ end
151
+ end
152
+ end # ts transition
153
+
154
+ describe "tS transition" do
155
+ before do
156
+ @net = @w.Net.of @p, @q, @tS
157
+ end
158
+
159
+ describe "no clamps" do
160
+ before do
161
+ @sim = @net.simulation net: @net
162
+ end
163
+
164
+ it "should behave" do
165
+ @sim.recording.must_equal( { 0 => [1, 2] } )
166
+ @sim.step!
167
+ @sim.recording.must_equal( { 0 => [1, 2], 1 => [2, 1] } )
168
+ end
169
+ end
170
+
171
+ describe "with clamps" do
172
+ before do
173
+ @sim = @net.simulation marking_clamps: { B: 43 }
174
+ end
175
+
176
+ it "should behave" do
177
+ @sim.recording.must_equal( { 0 => [1] } )
178
+ 3.times do @sim.step! end
179
+ @sim.recording.must_equal( { 0 => [1], 1 => [2], 2 => [3], 3 => [4] } )
180
+ end
181
+ end
182
+ end # tS transition
183
+
184
+ describe "Ts transition" do
185
+ before do
186
+ @net = @w.Net.of @p, @q, @Ts
187
+ end
188
+
189
+ describe "no clamps" do
190
+ before do
191
+ @sim = @net.simulation sampling: 1
192
+ end
193
+
194
+ it "should behave" do
195
+ @sim.timed?.must_equal true
196
+ @sim.simulation_method.must_equal :pseudo_euler
197
+ @sim.Ts_tt.size.must_equal 1
198
+ @sim.send( :transitions ).Ts.first.gradient_closure.call.must_equal 1
199
+ @sim.Ts_tt.first.codomain.names.must_equal [:A]
200
+ @sim.recording.must_equal( { 0.0 => [1, 2] } )
201
+ @sim.step! 1
202
+ @sim.recording.must_equal( { 0.0 => [1, 2], 1.0 => [2, 2] } )
203
+ end
204
+ end
205
+
206
+ describe "with clamps" do
207
+ before do
208
+ @sim = @net.simulation sampling: 1, marking_clamps: { B: 43 }
209
+ end
210
+
211
+ it "should behave" do
212
+ @sim.recording.must_equal( { 0.0 => [1] } )
213
+ 3.times do @sim.step! 1 end
214
+ @sim.recording.must_equal( { 0.0 => [1], 1.0 => [2], 2.0 => [3], 3.0 => [4] } )
215
+ end
216
+ end
217
+ end # Ts transition
218
+
219
+ describe "TS transition" do
220
+ before do
221
+ @net = @w.Net.of @p, @q, @TS
222
+ end
223
+
224
+ describe "no clamps" do
225
+ before do
226
+ @sim = @net.simulation sampling: 1
227
+ end
228
+
229
+ it "should behave" do
230
+ @sim.recording.must_be_kind_of YPetri::Net::State::Features::Dataset
231
+ @sim.recording.must_equal @net.State.marking.new_dataset.update( 0.0 => [1, 2] )
232
+ @sim.recording.must_equal( { 0.0 => [1, 2] } )
233
+ @sim.step! 1
234
+ @sim.recording.must_equal( { 0.0 => [1, 2], 1.0 => [2, 1] } )
235
+ end
236
+ end
237
+
238
+ describe "with clamps" do
239
+ before do
240
+ @sim = @net.simulation sampling: 1, marking_clamps: { B: 43 }
241
+ end
242
+
243
+ it "should behave" do
244
+ @sim.recording.must_equal( { 0.0 => [1] } )
245
+ 3.times do @sim.step! end
246
+ @sim.recording.must_equal( { 0.0 => [1], 1.0 => [2], 2.0 => [3], 3.0 => [4] } )
247
+ end
248
+ end
249
+ end # TS transition
250
+ end # transition representation aspects
247
251
  end
252
+ end
248
253
 
249
- it "5. handles sR transitions" do
250
- assert_equal [], @s.rate_closures_for_sR
251
- assert_equal [], @s.rate_closures_for_s
252
- # @s.gradient_for_sR.must_equal Matrix.zero( @s.free_pp.size, 1 )
253
- @s.Δ_sR( 1.0 ).must_equal Matrix.zero( @s.free_pp.size, 1 )
254
- end
255
254
 
256
- it "6. handles stoichiometric transitions with rate" do
257
- @s.rate_closures_for_SR.size.must_equal 3
258
- @s.rate_closures_for_S.size.must_equal 3
259
- @s.rate_closures.size.must_equal 3
260
- @s.flux_vector_for_SR.must_equal Matrix.column_vector( [ 0.4, 1.0, 1.5 ] )
261
- @s.φ_for_SR.must_equal @s.flux_vector
262
- @s.SR_tt( :φ_for_SR ).must_equal( { T1: 0.4, T2: 1.0, T3: 1.5 } )
263
- @s.first_order_action_vector_for_SR( 1 )
264
- .must_equal Matrix.column_vector [ 0.4, 1.0, 1.5 ]
265
- @s.SR_tt( :first_order_action_for_SR, 1 ).must_equal( T1: 0.4, T2: 1.0, T3: 1.5 )
266
- @s.Δ_SR( 1 ).must_equal Matrix[[-1.9], [1.0], [1.9]]
267
- @s.free_pp( :Δ_SR, 1 ).must_equal( { P2: -1.9, P3: 1.0, P4: 1.9 } )
255
+ describe YPetri::Simulation do
256
+ before do
257
+ self.class.class_exec { include YPetri }
258
+ U = Place m!: 2.5
259
+ V = Place m!: 2.5
260
+ Uplus = Transition codomain: :U do 1 end # s transition
261
+ U2V = Transition s: { U: -1, V: 1 } # S transition
262
+ set_ssc :Timeless, YPetri::Simulation::DEFAULT_SETTINGS.call
263
+ new_simulation ssc: :Timeless
264
+ 5.times do simulation.step! end
265
+ end
266
+
267
+ it "should behave" do
268
+ simulation.tap do |s|
269
+ assert ! s.timed?
270
+ s.core.must_be_kind_of YPetri::Core::Timeless::PseudoEuler
271
+ s.recording.size.must_equal 6
272
+ s.recording.events.must_equal [0, 1, 2, 3, 4, 5]
273
+ s.recording.reconstruct( event: 2 ).pm.must_equal( { U: 2.5, V: 4.5 } )
274
+ s.recording.marking.slice( 2..4 ).series
275
+ .must_equal [[2.5, 2.5, 2.5], [4.5, 5.5, 6.5]]
276
+ s.recording.marking( slice: 2..4 )
277
+ .must_equal( { 2 => [2.5, 4.5],
278
+ 3 => [2.5, 5.5],
279
+ 4 => [2.5, 6.5] } )
280
+ s.recording.firing_series( slice: 1..2 )
281
+ .must_equal [[1, 1]]
282
+ s.recording.firing_series( transitions: [:U2V] )
283
+ .must_equal [[1, 1, 1, 1, 1, 1]]
284
+ s.recording.delta_series( places: [:U], transitions: [:Uplus] )
285
+ .must_equal [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0]]
286
+ tmp = s.recording.features( marking: [:U], firing: [:U2V] )
287
+ tmp.delete( :features )
288
+ .must_equal( { marking: [:U], firing: [:U2V],
289
+ delta: { places: [], transitions: [] } } )
290
+ tmp.must_equal( { 0 => [2.5, 1], 1 => [2.5, 1], 2 => [2.5, 1],
291
+ 3 => [2.5, 1], 4 => [2.5, 1], 5 => [2.5, 1] } )
292
+ end
268
293
  end
294
+ end
269
295
 
270
- it "presents sparse stoichiometry vectors for its transitions" do
271
- @s.sparse_σ( @t1 ).must_equal Matrix.cv( [-1, 0, 1] )
272
- @s.sparse_stoichiometry_vector( @t1 )
273
- .must_equal Matrix.cv( [-1, -1, 0, 1, 0] )
274
- end
275
296
 
276
- it "presents correspondence matrices free, clamped => all places" do
277
- @s.F2A.must_equal Matrix[[0, 0, 0], [1, 0, 0], [0, 1, 0],
278
- [0, 0, 1], [0, 0, 0]]
279
- @s.C2A.must_equal Matrix[[1, 0], [0, 0], [0, 0], [0, 0], [0, 1]]
297
+ describe YPetri::Simulation::Timed do
298
+ before do
299
+ skip
300
+ self.class.class_exec { include YPetri }
301
+ A = Place m!: 0.5
302
+ B = Place m!: 0.5
303
+ A_pump = T s: { A: -1 } do 0.005 end
304
+ B_decay = Transition s: { B: -1 }, rate: 0.05
305
+ run!
306
+ end
307
+
308
+ it "should behave" do
309
+ places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected
310
+ simulation.tap do |s|
311
+ s.settings.must_equal( { method: :pseudo_euler, guarded: false,
312
+ step: 0.1, sampling: 5, time: 0..60 } )
313
+ assert s.recording.to_csv.start_with?( "0.0,0.5,0.5\n" +
314
+ "5.0,0.475,0.38916\n" +
315
+ "10.0,0.45,0.30289\n" +
316
+ "15.0,0.425,0.23574\n" +
317
+ "20.0,0.4,0.18348\n" +
318
+ "25.0,0.375,0.1428\n" )
319
+ assert s.recording.to_csv.end_with?( "60.0,0.2,0.02471" )
320
+ s.recording.events.must_equal [ 0.0, 5.0, 10.0, 15.0, 20.0,
321
+ 25.0, 30.0, 35.0, 40.0, 45.0,
322
+ 50.0, 55.0, 60.0 ]
323
+ s.recording.values_at( 5, 10 )
324
+ .must_equal [ [0.475, 0.38916], [0.45, 0.30289] ]
325
+ s.recording.slice( 2..12 )
326
+ .must_equal( { 5.0 => [0.475, 0.38916], 10.0=>[0.45, 0.30289] } )
327
+ s.recording.net
328
+ .must_equal net
329
+ s.recording.features
330
+ .must_equal net.State.marking( [:A, :B] )
331
+ net.State.Features.State
332
+ .must_equal net.State
333
+ s.recording.State
334
+ .must_equal net.State
335
+ s.recording.series( marking: [:A] )
336
+ .must_equal [ [ 0.5, 0.475, 0.45, 0.425, 0.4, 0.375, 0.35, 0.325,
337
+ 0.3, 0.275, 0.25, 0.225, 0.2 ] ]
338
+ s.recording.firing.series
339
+ .must_equal []
340
+ s.recording.firing
341
+ .must_equal( [*0..12].map { |n| n * 5.0 } >> [[]] * 13 )
342
+ # It is obvious why this fails: Given delta feature is not in the
343
+ # recording. It has to be generated, and since the net is timed,
344
+ # it also requires Δt to be generated.
345
+
346
+ # I'll comment it out for a while to see what the plot is doing.
347
+ =begin
348
+ s.recording.delta( [:A], transitions: [:A_pump] )
349
+ .must_equal [ [ -0.0005 ] * 13 ]
350
+ =end
351
+ plot_state
352
+ sleep 5
353
+ end
280
354
  end
281
355
  end