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.
@@ -3,596 +3,18 @@
3
3
  # Public command interface of YPetri.
4
4
  #
5
5
  class YPetri::Manipulator
6
-
7
- # Current workspace.
8
- #
9
- def workspace;
10
- # puts "Manipulator is #{self}, obj. id #{object_id}."
11
- @workspace
12
- end
6
+ attr_reader :workspace
13
7
 
14
8
  def initialize
15
- new_workspace_instance = YPetri::Workspace.new
16
- @workspace = new_workspace_instance
17
- net_point_reset
18
- net_selection_clear
19
- simulation_point_reset
20
- simulation_selection_clear
21
- ssc_point_reset
22
- ssc_selection_clear
23
- cc_point_reset
24
- cc_selection_clear
25
- imc_point_reset
26
- imc_selection_clear
27
- end
28
-
29
- delegate :place, :transition, :p, :t,
30
- :places, :transitions, :nets, :simulations,
31
- :pp, :tt, :nn,
32
- :clamp_collections,
33
- :initial_marking_collections,
34
- :simulation_settings_collections,
35
- :clamp_cc, :initial_marking_cc, :simulation_settings_cc,
36
- to: :workspace
37
-
38
- # Place constructor: Creates a new place in the current workspace.
39
- #
40
- def Place *args, &block
41
- workspace.Place.new *args, &block
42
- end
43
-
44
- # Transiton constructor: Creates a new transition in the current workspace.
45
- #
46
- def Transition *args, &block
47
- workspace.Transition.new *args, &block
48
- end
49
-
50
- # Net constructor: Creates a new Net instance in the current workspace.
51
- #
52
- def Net *args, &block
53
- workspace.Net.new *args, &block
54
- end
55
-
56
- # ==== Net point
57
-
58
- # Sets net point to workspace.Net::Top
59
- #
60
- def net_point_reset
61
- net_point_to( workspace.Net::Top )
62
- end
63
-
64
- # Sets net point to the one identified in the argument (Net instance or
65
- # its name).
66
- #
67
- def net_point_to which_net
68
- @net_point = workspace.net which_net
69
- end
70
- alias :net→ :net_point_to
71
-
72
- # Returns the net identified by the argument, or the net at the point, if
73
- # none given.
74
- #
75
- def net which=nil
76
- which.nil? ? @net_point : workspace.net( which )
77
- end
78
-
79
- # Returns the name of the net identified by the argument, or the net at the
80
- # point (if no argument is given).
81
- #
82
- def n which=nil
83
- net( which ).name
84
- end
85
-
86
- # ==== Simulation point
87
-
88
- # Sets simulation point to the first key of the workspace's collection of
89
- # simulations (or nil if there are no simulations yet).
90
- #
91
- def simulation_point_reset
92
- @simulation_point =
93
- workspace.simulations.empty? ? nil :
94
- simulation_point_to( workspace.simulations.first[0] )
95
- end
96
-
97
- # Sets simulation point to the simulation identified by the argument.
98
- # A simulation can be identified either by its name (if named), or by
99
- # its parameters and settings (simulated net, clamp collection, initial
100
- # marking collection, and simulation settings collection).
101
- #
102
- # If a single ordered (non-hash) argument is supplied, it is assumed to be
103
- # a simulation name. If a hash is supplied, it is expected that it will
104
- # contain four pairs with keys :net, :cc, :imc, :ssc, identifying the
105
- # simulation by its parameters and settings. Alternatively, use of hash
106
- # can be forgone - if exactly 4 ordered arguments are supplied, it is
107
- # assumed that they specified the parameter settings in the order set forth
108
- # earlier.
109
- #
110
- def simulation_point_to *args
111
- key = normalize_simulation_identifier *args
112
- @simulation_point = if key.nil? then nil
113
- elsif workspace.simulations.has_key? key then key
114
- else raise "No such simulation" end
115
- end
116
- alias :sim→ :simulation_point_to
117
-
118
- # Returns the simulation identified by the argument, or one indicated by the
119
- # simulation point (if no argument was given). The simulation is identified
120
- # by the arguments in the same way as for #simulation_point_to method.
121
- #
122
- def simulation *args
123
- workspace.simulation( normalize_simulation_identifier *args )
124
- end
125
-
126
- # TEMPORARY KLUGE - FIXME
127
- #
128
- def simulation; @workspace.simulations.values[-1] end
129
-
130
- # Returns the index (position) of the simulation point.
131
- #
132
- def simulation_point_position
133
- # FIXME: Change @simulations from being a has of { key => simulation } pairs
134
- # to be the hash of { simulation => names } pairs, in which simulations are
135
- # looked up either by rassoc or by sniffing their parameters and settings.
136
- @simulation_point
137
- end
138
-
139
- # ==== cc point (cc = clamp collection)
140
-
141
- # Clamp collections are stored in workplace in a hash. The cc point
142
- # points to its keys.
143
-
144
- # Resets cc point to :base.
145
- #
146
- def cc_point_reset
147
- @cc_point = :Base
148
- end
149
-
150
- # Sets the cc point to the specified cc.
151
- #
152
- def cc_point_to arg
153
- if workspace.clamp_collections.has_key? arg
154
- @cc_point = arg
155
- else
156
- raise "No clamp collection #{arg} in this workspace"
157
- end
158
- end
159
- alias :cc→ :cc_point_to
160
-
161
- # Returns clamp collection corresp. to cc point (if no argument), or to
162
- # the argument (if this was given).
163
- #
164
- def clamp_collection collection_name=nil
165
- cɴ = collection_name.nil? ? @cc_point : collection_name
166
- workspace.clamp_collections[ cɴ ] or
167
- raise AE, "No clamp collection #{cɴ} in this workspace."
168
- end
169
- alias :cc :clamp_collection
170
-
171
- # Returns the cc point position (cc hash key).
172
- #
173
- def cc_point_position; @cc_point end
174
-
175
- # ==== imc point ( imc = initial marking collection )
176
-
177
- # Initial marking collections are stored in a workplace in a hash.
178
- # The imc point points to its keys.
179
-
180
- # Resets imc point to :base.
181
- #
182
- def imc_point_reset; @imc_point = :Base end
183
-
184
- # Sets the imc point to the specified imc.
185
- #
186
- def imc_point_to arg
187
- if workspace.initial_marking_collections.has_key? arg
188
- @imc_point = arg
189
- else
190
- raise "No initial marking collection #{arg} in this workspace."
191
- end
192
- end
193
- alias :imc→ :imc_point_to
194
-
195
- # Returns initial marking collection corresp. to imc point (if no
196
- # argument), or to the argument (if this was given).
197
- #
198
- def initial_marking_collection collection_name=nil
199
- cɴ = collection_name.nil? ? @imc_point : collection_name
200
- workspace.initial_marking_collections[ cɴ ] or
201
- raise AE, "No initial marking collection #{cɴ} in this workspace."
202
- end
203
- alias :imc :initial_marking_collection
204
-
205
- # Returns the ssc point position (ssc hash key).
206
- #
207
- def imc_point_position; @imc_point end
208
-
209
- # ==== ssc point (ssc = simulation settings collection)
210
-
211
- # Simulation settings collections are stored in workplace in a hash.
212
- # The ssc point of manipulator points to its keys.
213
-
214
- # Resets ssc point to :base.
215
- #
216
- def ssc_point_reset; @ssc_point = :Base end
217
-
218
- # Sets the ssc point to the specified ssc.
219
- #
220
- def ssc_point_to arg
221
- if workspace.simulation_settings_collections.has_key? arg
222
- @ssc_point = arg
223
- else raise "No such simulation settings collection: #{arg}" end
224
- end
225
- alias :ssc→ :ssc_point_to
226
-
227
- # Returns the ssc identified by the argument, or that at ssc point (if no
228
- # argument is given).
229
- #
230
- def simulation_settings_collection collection_name=nil
231
- cɴ = collection_name.nil? ? @ssc_point : collection_name
232
- # puts "Target workspace is #{workspace}, obj. id #{workspace.object_id}"
233
- workspace.simulation_settings_collections[ cɴ ] or
234
- raise AE, "No simulations settings collection #{cɴ} in this workspace."
235
- end
236
- alias :ssc :simulation_settings_collection
237
-
238
- # Returns the ssc point position (ssc hash key).
239
- #
240
- def ssc_point_position; @ssc_point end
241
-
242
-
243
- # ==== Selection mechanism for net, simulation, cc, imc and ssc
244
- # TODO
245
-
246
- # Net selection.
247
- #
248
- attr_reader :net_selection
249
-
250
- # Simulation selection.
251
- #
252
- attr_reader :simulation_selection
253
-
254
- # Simulation settings collection selection.
255
- #
256
- attr_reader :ssc_selection
257
-
258
- # Clamp collection selection.
259
- #
260
- attr_reader :cc_selection
261
-
262
- # Initial marking collection selection.
263
- #
264
- attr_reader :imc_selection
265
-
266
- # ==== Net selection
267
-
268
- def net_selection_clear
269
- @net_selection ||= []
270
- @net_selection.clear
271
- end
272
-
273
- def net_select! *aa; net_selection_clear; net_select *aa end
274
-
275
- def net_select *aa
276
- case aa.size
277
- when 0 then ( @net_selection << net ).uniq!
278
- when 1 then ( @net_selection << aa[0] ).uniq!
279
- else aa.each { |a| net_select a } end
280
- end
281
-
282
- def net_unselect *aa
283
- if aa.empty? then @net_selection.delete net else
284
- aa.each { |arg| @net_selection.delete net( arg ) }
285
- end
286
- end
287
-
288
- # --- simulation selection ---------------------------------------------
289
-
290
- def simulation_selection_clear
291
- @simulation_selection ||= []
292
- @simulation_selection.clear
293
- end
294
-
295
- def simulation_select! *aa
296
- simulation_selection_clear
297
- simulation_select *aa
298
- end
299
-
300
- def simulation_select *aa
301
- # FIXME
302
- end
303
-
304
- def simulation_unselect *aa
305
- # FIXME
306
- end
307
-
308
- # --- cc selection -----------------------------------------------------
309
-
310
- def cc_selection_clear; @cc_selection ||= []; @cc_selection.clear end
311
-
312
- def cc_select! *aa; cc_selection_clear; cc_select *aa end
313
-
314
- def cc_select
315
- # FIXME
316
- end
317
-
318
- def cc_unselect *aa
319
- # FIXME
320
- end
321
-
322
- # --- imc selection ----------------------------------------------------
323
-
324
- def imc_selection_clear; @imc_selection ||= []; @imc_selection.clear end
325
-
326
- def imc_select! *aa; imc_selection_clear; imc_select *aa end
327
-
328
- def imc_select
329
- # FIXME
330
- end
331
-
332
- def imc_unselect *aa
333
- # FIXME
9
+ @workspace = YPetri::Workspace.new
10
+ super
334
11
  end
335
12
 
336
- # --- ssc selection ----------------------------------------------------
13
+ require_relative 'manipulator/selection'
14
+ require_relative 'manipulator/hash_key_pointer'
15
+ require_relative 'manipulator/petri_net_related_methods'
16
+ require_relative 'manipulator/simulation_related_methods'
337
17
 
338
- def ssc_selection_clear; @ssc_selection ||= []; @ssc_selection.clear end
339
-
340
- def ssc_select! *aa; ssc_selection_clear; ssc_select *aa end
341
-
342
- def ssc_select
343
- # FIXME
344
- end
345
-
346
- def ssc_unselect *aa
347
- # FIXME
348
- end
349
-
350
- # --- rest of the world ------------------------------------------------
351
- # FIXME: This is going to be tested
352
-
353
- def clamp clamp_hash
354
- clamp_hash.each_pair { |pl, cl|
355
- clamp_collection.merge! workspace.place( pl ) => cl
356
- }
357
- end
358
-
359
- # Returns or modifies current initial marking(s) as indicated by the argument
360
- # field:
361
- # * No arguments: returns current imc
362
- # * Exactly one ordered argument: it is assumed to identify a place whose
363
- # im in teh current imc will be returned.
364
- # * A hash: Assumed to be { place_id => im }, current imc is updated with it.
365
- # * One ordered argument, and a hash: The imc identified by the ordered
366
- # ordered arg is updated with the hash.
367
- # * 2 ordered arguments: First is assumed to identify an imc, second place
368
- # whose im acc. to that imc to return.
369
- #
370
- def initial_marking *args;
371
- oo = args.extract_options!
372
- case args.size
373
- when 0 then
374
- if oo.empty? then # no ordered arguments were given,
375
- initial_marking_collection # current imc will be returned
376
- else # hash was supplied, assumed of pairs { place_id => marking },
377
- initial_marking_collection # it will be merged to imc
378
- .update( oo.with_keys do |key| place( key ) end )
379
- end
380
- when 1 then # exactly one ordered argument was given,
381
- if oo.empty? then # without any named arguments, it is
382
- place = place( args[0] ) # assumed that it identifies a place,
383
- initial_marking_collection[ place ] # return its init. marking in imc
384
- else # One ordered argument (imc), and one hash (update values) given.
385
- im_coll = initial_marking_collection( args[0] )
386
- im_coll.update( oo.with_keys do |key| place( key ) end )
387
- end
388
- when 2 then # 2 ordered arguments (imc, place whose marking to return)
389
- im_coll = initial_marking_collection( args[0] )
390
- place = place( args[1] )
391
- im_coll[ place ]
392
- else raise AE, "Too many ordered parameters" end
393
- end
394
- alias :im :initial_marking
395
-
396
- # Changes the time step of the current ssc (ssc = simulation settings
397
- # collection).
398
- #
399
- def set_step Δt
400
- ssc.update step_size: Δt
401
- end
402
- alias :set_step_size :set_step
403
-
404
- # Changes the simulation time of the current ssc (ssc = simulation
405
- # settings collection).
406
- #
407
- def set_time t
408
- ssc.update target_time: t
409
- end
410
- alias :set_target_time :set_time
411
-
412
- # Changes the sampling period of the current ssc (ssc = simulation
413
- # settings collection).
414
- #
415
- def set_sampling Δt
416
- ssc.update sampling_period: Δt
417
- end
418
-
419
- # Changes the simulation method of the current ssc (ssc = simulation
420
- # settings collection).
421
- #
422
- def set_simulation_method m
423
- ssc.update method: m
424
- end
425
-
426
- # Create a new timed simulation and make it available in the simulations
427
- # table.
428
- #
429
- def new_timed_simulation *args, &block
430
- instance = workspace.new_timed_simulation( *args, &block )
431
- # Set the point to it
432
- simulation_point_to( simulations.rassoc( instance )[0] )
433
- return instance
434
- end
435
-
436
- # Create a new timed simulation and run it.
437
- #
438
- def run!
439
- new_timed_simulation.run!
440
- end
441
-
442
- # Write the recorded samples in a file (csv).
443
- #
444
- def print_recording( filename = nil )
445
- if filename.nil? then
446
- puts simulation.recording_csv_string
447
- else
448
- File.open( filename, "w" ) do |f|
449
- f << simulation.recording_csv_string
450
- end
451
- end
452
- end
453
-
454
- # Plot the recorded samples.
455
- #
456
- def plot *args
457
- oo = args.extract_options!
458
- case args.size
459
- when 0 then plot_recording oo
460
- when 1 then
461
- plot_what = args[0]
462
- case plot_what
463
- when :state then plot_recording oo
464
- when :flux then plot_flux oo
465
- when :all then plot_all oo
466
- else plot_selected *args end
467
- else raise "Too many ordered arguments!" end
468
- end
469
-
470
- # Plot the selected features.
471
- #
472
- def plot_selected *args
473
- oo = args.extract_options!
474
- collection = Array args[0]
475
- return nil unless sim = @workspace.simulations.values[-1] # sim@point
476
- # Decide abnout the features
477
- features = sim.places.dup.map { |p|
478
- collection.include?( p ) ? p : nil
479
- }
480
- # Get recording
481
- rec = sim.recording
482
- # Select a time series for each feature.
483
- time_series = features.map.with_index do |feature, i|
484
- feature and rec.map { |key, val| [ key, val[i] ] }.transpose
485
- end
486
- # Time axis
487
- ᴛ = sim.target_time
488
- # Gnuplot call
489
- gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
490
- title: "Selected features plot", ylabel: "Marking" )
491
- end
492
-
493
-
494
- # Plot the recorded samples (system state history).
495
- #
496
- def plot_state( *args )
497
- oo = args.extract_options!
498
- excluded = Array oo[:except]
499
- return nil unless sim = @workspace.simulations.values[-1] # sim@point
500
- # Decide about the features to plot.
501
- features = excluded.each_with_object sim.places.dup do |x, α|
502
- i = α.index x
503
- α[i] = nil if i
504
- end
505
- # Get recording
506
- rec = sim.recording
507
- # Select a time series for each feature.
508
- time_series = features.map.with_index do |feature, i|
509
- feature and rec.map { |key, val| [ key, val[i] ] }.transpose
510
- end
511
- # Time axis
512
- ᴛ = sim.target_time
513
- # Gnuplot call
514
- gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
515
- title: "State plot", ylabel: "Marking" )
516
- end
517
-
518
- # Plot the recorded flux (computed flux history at the sampling points).
519
- #
520
- def plot_flux( *args )
521
- oo = args.extract_options!
522
- excluded = Array oo[:except]
523
- return nil unless sim = @workspace.simulations.values[-1] # sim@point
524
- # Decide about the features to plot.
525
- all = sim.SR_transitions
526
- features = excluded.each_with_object all.dup do |x, α|
527
- i = α.index x
528
- if i then α[i] = nil end
529
- end
530
- # Get recording.
531
- rec = sim.recording
532
- # Get flux recording.
533
- flux = rec.modify { |ᴛ, ᴍ| [ ᴛ, sim.at( t: ᴛ, m: ᴍ ).flux_for( *all ) ] }
534
- # Select a time series for each feature.
535
- time_series = features.map.with_index do |feature, i|
536
- feature and flux.map { |ᴛ, flux| [ ᴛ, flux[i] ] }.transpose
537
- end
538
- # Time axis
539
- ᴛ = sim.target_time
540
- # Gnuplot call
541
- gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
542
- title: "Flux plot", ylabel: "Flux [µMⁿ.s⁻¹]" )
543
- end
544
-
545
- private
546
-
547
- # Gnuplots things.
548
- #
549
- def gnuplot( time, labels, time_series, *args )
550
- labels = labels.dup
551
- time_series = time_series.dup
552
- oo = args.extract_options!
553
-
554
- Gnuplot.open do |gp|
555
- Gnuplot::Plot.new( gp ) do |plot|
556
- plot.xrange "[-0:#{SY::Time.magnitude( time ).amount rescue time}]"
557
- plot.title oo[:title] || "Simulation plot"
558
- plot.ylabel oo[:ylabel] || "Values"
559
- plot.xlabel oo[:xlabel] || "Time [s]"
560
-
561
- labels.zip( time_series ).each { |label, series|
562
- plot.data << Gnuplot::DataSet.new( series ) do |data_series|
563
- data_series.with = "linespoints"
564
- data_series.title = label
565
- end
566
- }
567
- end
568
- end
569
- end
570
-
571
- # Helper method allowing more flexible access to the simulations stored in
572
- # the current workspace. A single, non-hash ordered argument is considered
573
- # a simulation name. A hash argument is assumed to be have keys :net, :cc,
574
- # :imc, :ssc, by which to identify a simulation. Hash keys can be forgone if
575
- # 4 ordered arguments are supplied: These are then considered to represent
576
- # the values of a hash with the above keys, and are converted to such hash.
577
- # Summarizing this, there is a single return value, with which a simulation
578
- # can be identified - this return value is either a hash of simulation
579
- # parameters and settings, if it is a hash, or a simulation name, if it is
580
- # non-hash.
581
- #
582
- def normalize_simulation_identifier *args
583
- oo = args.extract_options!
584
- if args.empty? then
585
- raise AE, "Simulation point position not supplied" if oo.empty?
586
- oo
587
- else
588
- if oo.empty? then
589
- case args.size
590
- when 1 then args[0]
591
- when 4 then Hash[ [:net, :cc, :imc, :ssc].zip( args ) ]
592
- else raise AE, "Wrong number of ordered arguments." end
593
- else
594
- raise AE, "Bad arguments: Can't combine named & ordered args."
595
- end
596
- end
597
- end
18
+ include YPetri::Manipulator::PetriNetRelatedMethods
19
+ include YPetri::Manipulator::SimulationRelatedMethods
598
20
  end # class YPetri::Manipulator