y_petri 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
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