y_petri 2.0.2 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4924585303a77bc040de2baf135ff544849460ee
4
- data.tar.gz: f006c579cc4bc39549b6ff66da0ffcb6ea34bb0a
3
+ metadata.gz: 7785c5d949ae026d98f538426713dbf8ba5c087b
4
+ data.tar.gz: ae69a454df83b31f1314dd2935282ab97e12653f
5
5
  SHA512:
6
- metadata.gz: c041dcddf16daf158db0c602f1ad18c555031d2fe12f3a5c86f728728ea2a950aa8e0c4508bfe4fac13f42c0c4f75570d7f1bb700cbc04a25b6c4b4c6fef2283
7
- data.tar.gz: 4636a534a2978c7155b79b0d40f630d01f40d4dc730bb7d46244b85db5ae27f1f08c224c0d11c4b4ae955f4a6fc50ade478354d22aa72498a21dd755ee154bb6
6
+ metadata.gz: 3a6cb9bc4a188d7de73fd3dd01067772be90ecfbd6f9673fb1adcfee464d590b9d470faeb154d07b89a95e930525ce3c090682817440a23b79829027e5cdf6d8
7
+ data.tar.gz: fdaed6c9020950aa17a2345567d8fdece08b2987f237aa3448ace6dc75ef14d8f417951ce39690f7de3fab7b24722f0bfcbfe888d151863771ca5f1328f36127
data/.gitignore CHANGED
@@ -17,4 +17,5 @@ rdoc
17
17
  spec/reports
18
18
  test/tmp
19
19
  test/version_tmp
20
+ test/*.png
20
21
  tmp
@@ -0,0 +1,38 @@
1
+ # Represents a pointer to a key of a specific hash associated with the pointer
2
+ # instance. Used to implement pointers of the Manipulator class.
3
+ #
4
+ class YPetri::Manipulator::HashKeyPointer
5
+ # Key at which the pointer points.
6
+ #
7
+ attr_reader :key
8
+
9
+ # Short text explaining what does a value of the associated hash represent.
10
+ #
11
+ attr_reader :what_is_hash_value
12
+
13
+ # Upon initalization, hash key pointer requires a hash, with which the
14
+ # instance will be associated, a textual description explaining what does
15
+ # a value of the associated hash represent, and the default hash key.
16
+ #
17
+ def initialize( hash: nil, hash_value_is: '', default_key: nil )
18
+ @hash = hash
19
+ @what_is_hash_value = hash_value_is
20
+ @default_key = default_key
21
+ end
22
+
23
+ # Resets the key to the default key.
24
+ #
25
+ def reset; @key = @default_key end
26
+
27
+ # Sets the pointer key to the one given in the argument.
28
+ #
29
+ def set arg; @key = arg end
30
+
31
+ # Gets the <em>value</em> paired in the hash associated with the current
32
+ # key to which this pointer points.
33
+ #
34
+ def get
35
+ return @hash[@default_key] if @key.nil?
36
+ @hash[@key] or raise "No #{what_is_hash_value} identified by #{arg}!"
37
+ end
38
+ end
@@ -0,0 +1,55 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Public command interface of YPetri.
3
+ #
4
+ module YPetri::Manipulator::PetriNetRelatedMethods
5
+ # Net selection class.
6
+ #
7
+ NetSelection = Class.new YPetri::Manipulator::Selection
8
+
9
+ # Net point
10
+ #
11
+ attr_reader :net_point
12
+
13
+ # Net selection.
14
+ #
15
+ attr_reader :net_selection
16
+
17
+ def initialize
18
+ net_point_reset
19
+ @net_selection = NetSelection.new
20
+ super
21
+ end
22
+
23
+ delegate :place, :transition, :pl, :tr,
24
+ :places, :transitions, :nets,
25
+ :pp, :tt, :nn, to: :workspace
26
+
27
+ # Place constructor: Creates a new place in the current workspace.
28
+ #
29
+ def Place *args, &b; workspace.Place.new *args, &b end
30
+
31
+ # Transiton constructor: Creates a new transition in the current workspace.
32
+ #
33
+ def Transition *args, &b; workspace.Transition.new *args, &b end
34
+
35
+ # Net constructor: Creates a new Net instance in the current workspace.
36
+ #
37
+ def Net *args, &b; workspace.Net.new *args, &b end
38
+
39
+ # Returns the net identified, or the net at point (if no argument given).
40
+ #
41
+ def net id=nil; id.nil? ? @net_point : workspace.net( id ) end
42
+
43
+ # Returns the name of the identified net, or of the net at point (if no
44
+ # argument given).
45
+ #
46
+ def ne id=nil; net( id ).name end
47
+
48
+ # Sets net point to workspace.Net::Top
49
+ #
50
+ def net_point_reset; net_point_set( workspace.Net::Top ) end
51
+
52
+ # Sets net point to the net identified by the argument (by name or instance).
53
+ #
54
+ def net_point_set id; @net_point = workspace.net( id ) end
55
+ end # module YPetri::Manipulator::PetriNetRelatedMethods
@@ -0,0 +1,11 @@
1
+ class YPetri::Manipulator::Selection
2
+ def initialize
3
+ clear
4
+ end
5
+ def clear; @selection = [] end
6
+ def set *aa; @selection = aa end
7
+ def get; @selection end
8
+ def add arg; @selection << arg end
9
+ alias :<< :add
10
+ def subtract arg; @selection -= arg end
11
+ end
@@ -0,0 +1,361 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Manipulator instance methods related to simulation (initial marking
3
+ # collections, clamp collections, initial marking collections, management
4
+ # of simulations...)
5
+ #
6
+ module YPetri::Manipulator::SimulationRelatedMethods
7
+ require_relative 'hash_key_pointer'
8
+ require_relative 'selection'
9
+
10
+ # Simulation selection class.
11
+ #
12
+ SimulationSelection = Class.new YPetri::Manipulator::Selection
13
+
14
+ # Simulation settings collection selection class.
15
+ #
16
+ SscSelection = Class.new YPetri::Manipulator::Selection
17
+
18
+ # Clamp collection selection class.
19
+ #
20
+ CcSelection = Class.new YPetri::Manipulator::Selection
21
+
22
+ # Initial marking collection selection class.
23
+ #
24
+ ImcSelection = Class.new YPetri::Manipulator::Selection
25
+
26
+ class SimulationPoint < YPetri::Manipulator::HashKeyPointer
27
+ # Reset to the first simulation, or nil if that is absent.
28
+ #
29
+ def reset; @key = @hash.empty? ? nil : set( @hash.first[0] ) end
30
+
31
+ # A simulation is identified either by its name (if named), or by its
32
+ # parameters and settings (:net, :cc, :imc, :ssc).
33
+ #
34
+ def set *args
35
+ key = identify *args
36
+ @key = if key.nil? then key
37
+ elsif @hash.has_key? key then key
38
+ else raise "No simulation identified by #{key}!" end
39
+ end
40
+
41
+ # Helper method specifying how a simulation is identified by arguments.
42
+ #
43
+ def identify( simulation_name=nil, net: nil, cc: nil, imc: nil, ssc: nil )
44
+ simulation_name || { net: net, cc: cc, imc: imc, ssc: ssc }
45
+ end
46
+ end
47
+
48
+ # Pointer to a collection of simulation settings.
49
+ #
50
+ SscPoint = Class.new YPetri::Manipulator::HashKeyPointer
51
+
52
+ # Pointer to a clamp collection.
53
+ #
54
+ CcPoint = Class.new YPetri::Manipulator::HashKeyPointer
55
+
56
+ # Pointer to a collection of initial markings.
57
+ #
58
+ ImcPoint = Class.new YPetri::Manipulator::HashKeyPointer
59
+
60
+ attr_reader :simulation_point, :ssc_point, :cc_point, :imc_point,
61
+ :simulation_selection, :ssc_selection,
62
+ :cc_selection, :imc_selection
63
+
64
+ def initialize
65
+ # set up this manipulator's pointers
66
+ @simulation_point = SimulationPoint.new( hash: simulations,
67
+ hash_value_is: "simulation" )
68
+ @ssc_point = SscPoint.new( hash: simulation_settings_collections,
69
+ hash_value_is: "simulation settings collection",
70
+ default_key: :Base )
71
+ @cc_point = CcPoint.new( hash: clamp_collections,
72
+ hash_value_is: "clamp collection",
73
+ default_key: :Base )
74
+ @imc_point = ImcPoint.new( hash: initial_marking_collections,
75
+ hash_value_is: "initial marking collection",
76
+ default_key: :Base )
77
+ # set up this manipulator's selections
78
+ @simulation_selection = SimulationSelection.new
79
+ @ssc_selection = SscSelection.new
80
+ @cc_selection = CcSelection.new
81
+ @imc_selection = ImcSelection.new
82
+ # do anything else prescribed
83
+ super
84
+ end
85
+
86
+ # Simulation-related methods delegated to the workspace.
87
+ delegate :simulations,
88
+ :clamp_collections,
89
+ :initial_marking_collections,
90
+ :simulation_settings_collections,
91
+ :clamp_collection_names, :cc_names,
92
+ :initial_marking_collection_names, :imc_names,
93
+ :simulation_settings_collection_names, :ssc_names,
94
+ :set_clamp_collection, :set_cc,
95
+ :set_initial_marking_collection, :set_imc,
96
+ :set_simulation_settings_collection, :set_ssc,
97
+ :new_timed_simulation,
98
+ :clamp_cc, :initial_marking_cc, :simulation_settings_cc,
99
+ to: :workspace
100
+
101
+ # Returns the simulation identified by the argument, or one at simulation
102
+ # point, if no argument given. The simulation is identified in the same way
103
+ # as for #simulation_point_to method.
104
+ #
105
+ def simulation *args
106
+ return simulation_point.get if args.empty?
107
+ SimulationPoint.new( hash: simulations, hash_value_is: "simulation" ).get
108
+ end
109
+
110
+ # # TEMPORARY KLUGE - FIXME
111
+ # #
112
+ # def simulation; @workspace.simulations.values[-1] end
113
+
114
+ # Returns identified clamp collection, or (if no argument given) one
115
+ # corresponding to cc_point.
116
+ #
117
+ def clamp_collection id=nil
118
+ if id.nil? then cc_point.get else clamp_collections[ id ] end
119
+ end
120
+ alias cc clamp_collection
121
+
122
+ # Returns identified initial marking collection, or (if no argument given)
123
+ # one corresponding to imc_point.
124
+ #
125
+ def initial_marking_collection id=nil
126
+ if id.nil? then imc_point.get else
127
+ initial_marking_collections[ id ]
128
+ end
129
+ end
130
+ alias imc initial_marking_collection
131
+
132
+ # Returns identified simulation settings collection, or (if no argument given)
133
+ # one corresponding to ssc_point.
134
+ #
135
+ def simulation_settings_collection id=nil
136
+ if id.nil? then ssc_point.get else
137
+ simulation_settings_collections[ id ]
138
+ end
139
+ end
140
+ alias ssc simulation_settings_collection
141
+
142
+ # FIXME: This is going to be tested
143
+
144
+ def clamp clamp_hash
145
+ clamp_hash.each_pair do |place, clamp|
146
+ clamp_collection.merge! workspace.place( place ) => clamp
147
+ end
148
+ end
149
+
150
+ # Returns or modifies current initial marking(s) as indicated by the argument
151
+ # field:
152
+ # * No arguments: returns current imc
153
+ # * Exactly one ordered argument: it is assumed to identify a place whose
154
+ # im in teh current imc will be returned.
155
+ # * A hash: Assumed to be { place_id => im }, current imc is updated with it.
156
+ # * One ordered argument, and a hash: The imc identified by the ordered
157
+ # ordered arg is updated with the hash.
158
+ # * 2 ordered arguments: First is assumed to identify an imc, second place
159
+ # whose im acc. to that imc to return.
160
+ #
161
+ def initial_marking *args;
162
+ oo = args.extract_options!
163
+ case args.size
164
+ when 0 then
165
+ if oo.empty? then # no ordered arguments were given,
166
+ initial_marking_collection # current imc will be returned
167
+ else # hash was supplied, assumed of pairs { place_id => marking },
168
+ initial_marking_collection # it will be merged to imc
169
+ .update( oo.with_keys do |key| place( key ) end )
170
+ end
171
+ when 1 then # exactly one ordered argument was given,
172
+ if oo.empty? then # without any named arguments, it is
173
+ place = place( args[0] ) # assumed that it identifies a place,
174
+ initial_marking_collection[ place ] # return its init. marking in imc
175
+ else # One ordered argument (imc), and one hash (update values) given.
176
+ im_coll = initial_marking_collection( args[0] )
177
+ im_coll.update( oo.with_keys do |key| place( key ) end )
178
+ end
179
+ when 2 then # 2 ordered arguments (imc, place whose marking to return)
180
+ im_coll = initial_marking_collection( args[0] )
181
+ place = place( args[1] )
182
+ im_coll[ place ]
183
+ else raise ArgumentError, "Too many ordered parameters" end
184
+ end
185
+ alias im initial_marking
186
+
187
+ # Changes the time step of the current ssc (ssc = simulation settings
188
+ # collection).
189
+ #
190
+ def set_step Δt
191
+ ssc.update step_size: Δt
192
+ end
193
+ alias set_step_size set_step
194
+
195
+ # Changes the simulation time of the current ssc (ssc = simulation
196
+ # settings collection).
197
+ #
198
+ def set_time t
199
+ ssc.update target_time: t
200
+ end
201
+ alias set_target_time set_time
202
+
203
+ # Changes the sampling period of the current ssc (ssc = simulation
204
+ # settings collection).
205
+ #
206
+ def set_sampling Δt
207
+ ssc.update sampling_period: Δt
208
+ end
209
+
210
+ # Changes the simulation method of the current ssc (ssc = simulation
211
+ # settings collection).
212
+ #
213
+ def set_simulation_method m
214
+ ssc.update method: m
215
+ end
216
+
217
+ # Create a new timed simulation and make it available in the simulations
218
+ # table.
219
+ #
220
+ def new_timed_simulation *args, &block
221
+ instance = workspace.new_timed_simulation( *args, &block )
222
+ # Set the point to it
223
+ simulation_point.set( simulations.rassoc( instance )[0] )
224
+ return instance
225
+ end
226
+
227
+ # Create a new timed simulation and run it.
228
+ #
229
+ def run!
230
+ new_timed_simulation.run!
231
+ end
232
+
233
+ # Write the recorded samples in a file (csv).
234
+ #
235
+ def print_recording( filename = nil )
236
+ if filename.nil? then
237
+ puts simulation.recording_csv_string
238
+ else
239
+ File.open( filename, "w" ) do |f|
240
+ f << simulation.recording_csv_string
241
+ end
242
+ end
243
+ end
244
+
245
+ # Plot the recorded samples.
246
+ #
247
+ def plot *args
248
+ oo = args.extract_options!
249
+ case args.size
250
+ when 0 then plot_recording oo
251
+ when 1 then
252
+ plot_what = args[0]
253
+ case plot_what
254
+ when :state then plot_recording oo
255
+ when :flux then plot_flux oo
256
+ when :all then plot_all oo
257
+ else plot_selected *args end
258
+ else raise "Too many ordered arguments!" end
259
+ end
260
+
261
+ # Plot the selected features.
262
+ #
263
+ def plot_selected *args
264
+ oo = args.extract_options!
265
+ collection = Array args[0]
266
+ return nil unless sim = @workspace.simulations.values[-1] # sim@point
267
+ # Decide abnout the features
268
+ features = sim.places.dup.map { |p|
269
+ collection.include?( p ) ? p : nil
270
+ }
271
+ # Get recording
272
+ rec = sim.recording
273
+ # Select a time series for each feature.
274
+ time_series = features.map.with_index do |feature, i|
275
+ feature and rec.map { |key, val| [ key, val[i] ] }.transpose
276
+ end
277
+ # Time axis
278
+ ᴛ = sim.target_time
279
+ # Gnuplot call
280
+ gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
281
+ title: "Selected features plot", ylabel: "Marking" )
282
+ end
283
+
284
+
285
+ # Plot the recorded samples (system state history).
286
+ #
287
+ def plot_state( *args )
288
+ oo = args.extract_options!
289
+ excluded = Array oo[:except]
290
+ return nil unless sim = @workspace.simulations.values[-1] # sim@point
291
+ # Decide about the features to plot.
292
+ features = excluded.each_with_object sim.places.dup do |x, α|
293
+ i = α.index x
294
+ α[i] = nil if i
295
+ end
296
+ # Get recording
297
+ rec = sim.recording
298
+ # Select a time series for each feature.
299
+ time_series = features.map.with_index do |feature, i|
300
+ feature and rec.map { |key, val| [ key, val[i] ] }.transpose
301
+ end
302
+ # Time axis
303
+ ᴛ = sim.target_time
304
+ # Gnuplot call
305
+ gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
306
+ title: "State plot", ylabel: "Marking" )
307
+ end
308
+
309
+ # Plot the recorded flux (computed flux history at the sampling points).
310
+ #
311
+ def plot_flux( *args )
312
+ oo = args.extract_options!
313
+ excluded = Array oo[:except]
314
+ return nil unless sim = @workspace.simulations.values[-1] # sim@point
315
+ # Decide about the features to plot.
316
+ all = sim.SR_transitions
317
+ features = excluded.each_with_object all.dup do |x, α|
318
+ i = α.index x
319
+ if i then α[i] = nil end
320
+ end
321
+ # Get recording.
322
+ rec = sim.recording
323
+ # Get flux recording.
324
+ flux = rec.modify { |ᴛ, ᴍ| [ ᴛ, sim.at( t: ᴛ, m: ᴍ ).flux_for( *all ) ] }
325
+ # Select a time series for each feature.
326
+ time_series = features.map.with_index do |feature, i|
327
+ feature and flux.map { |ᴛ, flux| [ ᴛ, flux[i] ] }.transpose
328
+ end
329
+ # Time axis
330
+ ᴛ = sim.target_time
331
+ # Gnuplot call
332
+ gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
333
+ title: "Flux plot", ylabel: "Flux [µMⁿ.s⁻¹]" )
334
+ end
335
+
336
+ private
337
+
338
+ # Gnuplots things.
339
+ #
340
+ def gnuplot( time, labels, time_series, *args )
341
+ labels = labels.dup
342
+ time_series = time_series.dup
343
+ oo = args.extract_options!
344
+
345
+ Gnuplot.open do |gp|
346
+ Gnuplot::Plot.new( gp ) do |plot|
347
+ plot.xrange "[-0:#{SY::Time.magnitude( time ).amount rescue time}]"
348
+ plot.title oo[:title] || "Simulation plot"
349
+ plot.ylabel oo[:ylabel] || "Values"
350
+ plot.xlabel oo[:xlabel] || "Time [s]"
351
+
352
+ labels.zip( time_series ).each { |label, series|
353
+ plot.data << Gnuplot::DataSet.new( series ) do |data_series|
354
+ data_series.with = "linespoints"
355
+ data_series.title = label
356
+ end
357
+ }
358
+ end
359
+ end
360
+ end
361
+ end # module YPetri::Manipulator