y_petri 2.2.4 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +675 -0
  3. data/README.md +6 -3
  4. data/Rakefile +1 -1
  5. data/lib/y_petri/agent/{petri_net_related.rb → petri_net_aspect.rb} +34 -10
  6. data/lib/y_petri/agent/{simulation_related.rb → simulation_aspect.rb} +49 -34
  7. data/lib/y_petri/agent.rb +5 -5
  8. data/lib/y_petri/core/guarded.rb +24 -0
  9. data/lib/y_petri/core/timed/euler.rb +4 -8
  10. data/lib/y_petri/core/timed/gillespie.rb +11 -17
  11. data/lib/y_petri/core/timed/methods.rb +23 -0
  12. data/lib/y_petri/core/timed/pseudo_euler.rb +10 -13
  13. data/lib/y_petri/core/timed/quasi_euler.rb +9 -8
  14. data/lib/y_petri/core/timed/runge_kutta.rb +10 -18
  15. data/lib/y_petri/core/timed.rb +6 -14
  16. data/lib/y_petri/core/timeless/methods.rb +15 -0
  17. data/lib/y_petri/core/timeless/pseudo_euler.rb +4 -8
  18. data/lib/y_petri/core/timeless.rb +9 -4
  19. data/lib/y_petri/core.rb +44 -42
  20. data/lib/y_petri/net/data_set.rb +246 -142
  21. data/lib/y_petri/net/node_access.rb +282 -0
  22. data/lib/y_petri/net/own_state.rb +14 -4
  23. data/lib/y_petri/net/state/feature/assignment.rb +123 -0
  24. data/lib/y_petri/net/state/feature/delta.rb +55 -35
  25. data/lib/y_petri/net/state/feature/firing.rb +68 -25
  26. data/lib/y_petri/net/state/feature/flux.rb +9 -2
  27. data/lib/y_petri/net/state/feature/gradient.rb +36 -19
  28. data/lib/y_petri/net/state/feature/marking.rb +10 -5
  29. data/lib/y_petri/net/state/feature.rb +105 -11
  30. data/lib/y_petri/net/state/features/record.rb +144 -99
  31. data/lib/y_petri/net/state/features.rb +327 -200
  32. data/lib/y_petri/net/state.rb +48 -82
  33. data/lib/y_petri/net/visualization.rb +1 -1
  34. data/lib/y_petri/net.rb +62 -47
  35. data/lib/y_petri/place/arcs.rb +44 -0
  36. data/lib/y_petri/place/features.rb +115 -0
  37. data/lib/y_petri/place.rb +62 -29
  38. data/lib/y_petri/simulation/dependency.rb +31 -67
  39. data/lib/y_petri/simulation/feature_set.rb +1 -1
  40. data/lib/y_petri/simulation/initial_marking/access.rb +42 -26
  41. data/lib/y_petri/simulation/marking_clamps/access.rb +22 -17
  42. data/lib/y_petri/simulation/marking_clamps.rb +0 -2
  43. data/lib/y_petri/simulation/marking_vector/access.rb +102 -40
  44. data/lib/y_petri/simulation/marking_vector.rb +35 -37
  45. data/lib/y_petri/simulation/matrix.rb +1 -1
  46. data/lib/y_petri/simulation/node_representation.rb +25 -0
  47. data/lib/y_petri/simulation/nodes/access.rb +78 -0
  48. data/lib/y_petri/simulation/{elements.rb → nodes.rb} +14 -13
  49. data/lib/y_petri/simulation/place_mapping.rb +2 -2
  50. data/lib/y_petri/simulation/place_representation.rb +8 -7
  51. data/lib/y_petri/simulation/places/access.rb +89 -70
  52. data/lib/y_petri/simulation/places/free.rb +1 -1
  53. data/lib/y_petri/simulation/places/types.rb +20 -22
  54. data/lib/y_petri/simulation/places.rb +23 -18
  55. data/lib/y_petri/simulation/recorder.rb +23 -18
  56. data/lib/y_petri/simulation/timed/recorder.rb +19 -11
  57. data/lib/y_petri/simulation/timed.rb +93 -29
  58. data/lib/y_petri/simulation/timeless/recorder.rb +11 -6
  59. data/lib/y_petri/simulation/timeless.rb +13 -3
  60. data/lib/y_petri/simulation/transition_representation/A.rb +24 -4
  61. data/lib/y_petri/simulation/transition_representation/S.rb +11 -1
  62. data/lib/y_petri/simulation/transition_representation/T.rb +1 -1
  63. data/lib/y_petri/simulation/transition_representation/Ts.rb +1 -1
  64. data/lib/y_petri/simulation/transition_representation/a.rb +1 -1
  65. data/lib/y_petri/simulation/transition_representation/s.rb +12 -1
  66. data/lib/y_petri/simulation/transition_representation/t.rb +1 -1
  67. data/lib/y_petri/simulation/transition_representation/tS.rb +1 -1
  68. data/lib/y_petri/simulation/transition_representation/ts.rb +1 -1
  69. data/lib/y_petri/simulation/transition_representation/types.rb +1 -1
  70. data/lib/y_petri/simulation/transition_representation.rb +4 -11
  71. data/lib/y_petri/simulation/transitions/A.rb +17 -2
  72. data/lib/y_petri/simulation/transitions/S.rb +1 -1
  73. data/lib/y_petri/simulation/transitions/T.rb +1 -1
  74. data/lib/y_petri/simulation/transitions/Ts.rb +6 -5
  75. data/lib/y_petri/simulation/transitions/a.rb +1 -1
  76. data/lib/y_petri/simulation/transitions/access.rb +195 -168
  77. data/lib/y_petri/simulation/transitions/s.rb +1 -1
  78. data/lib/y_petri/simulation/transitions/t.rb +1 -1
  79. data/lib/y_petri/simulation/transitions/tS.rb +1 -1
  80. data/lib/y_petri/simulation/transitions/ts.rb +1 -1
  81. data/lib/y_petri/simulation/transitions/types.rb +1 -1
  82. data/lib/y_petri/simulation/transitions.rb +5 -7
  83. data/lib/y_petri/simulation.rb +84 -90
  84. data/lib/y_petri/transition/A.rb +8 -2
  85. data/lib/y_petri/transition/T.rb +25 -2
  86. data/lib/y_petri/transition/arcs.rb +19 -3
  87. data/lib/y_petri/transition/construction_convenience.rb +11 -10
  88. data/lib/y_petri/transition/t.rb +14 -1
  89. data/lib/y_petri/transition/types.rb +6 -1
  90. data/lib/y_petri/transition.rb +9 -12
  91. data/lib/y_petri/version.rb +1 -1
  92. data/lib/y_petri/world/dependency.rb +3 -3
  93. data/lib/y_petri/world/{petri_net_related.rb → petri_net_aspect.rb} +4 -4
  94. data/lib/y_petri/world/simulation_aspect.rb +352 -0
  95. data/lib/y_petri/world.rb +4 -4
  96. data/lib/y_petri.rb +1 -1
  97. data/test/agent_test.rb +2 -1
  98. data/test/examples/demonstrator.rb +4 -1
  99. data/test/examples/demonstrator_2.rb +5 -0
  100. data/test/examples/demonstrator_4.rb +6 -5
  101. data/test/examples/example_2.rb +2 -0
  102. data/test/examples/manual_examples.rb +4 -4
  103. data/test/net_test.rb +457 -54
  104. data/test/place_test.rb +11 -7
  105. data/test/simulation_test.rb +358 -331
  106. data/test/transition_test.rb +11 -10
  107. data/test/world_test.rb +2 -0
  108. data/test/y_petri_test.rb +2 -1
  109. data/y_petri.gemspec +24 -18
  110. metadata +71 -17
  111. data/LICENSE +0 -22
  112. data/lib/y_petri/net/element_access.rb +0 -239
  113. data/lib/y_petri/simulation/element_representation.rb +0 -20
  114. data/lib/y_petri/simulation/elements/access.rb +0 -57
  115. data/lib/y_petri/transition/type.rb +0 -103
  116. data/lib/y_petri/transition/type_information.rb +0 -103
  117. data/lib/y_petri/world/simulation_related.rb +0 -176
data/README.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # YPetri
2
2
 
3
- `YPetri` is a domain model and a simulator of _functional_ _Petri_ _nets_,
4
- a family of Petri nets, whose transitions have functions attached to them.
3
+ `YPetri` is a domain model and a simulator of _YPetri_ nets, a specific kind of
4
+ _Petri_ _nets_ unifying discrete/continous, deterministic/stochastic,
5
+ timed/timeless and stoichiometric/nonstoichiometric dichotomies, thus enabling
6
+ modelling and simulation of dynamic systems of any kind whatsoever.
5
7
 
6
8
  ## Usage
7
9
 
8
- `YPetri` provides a _domain_ _specific_ _language_ (DSL), that can be loaded by:
10
+ `YPetri` provides a _domain_ _specific_ _modeling_ _language_ (DSML), that can
11
+ be loaded by:
9
12
  ```ruby
10
13
  require 'y_petri'
11
14
  include YPetri
data/Rakefile CHANGED
@@ -1,2 +1,2 @@
1
- #!/usr/bin/env rake
2
1
  require "bundler/gem_tasks"
2
+
@@ -1,8 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Public command interface of YPetri.
3
+ # Petri net aspect of +YPetri::Agent+.
4
4
  #
5
- module YPetri::Agent::PetriNetRelated
5
+ module YPetri::Agent::PetriNetAspect
6
6
  # Net selection class.
7
7
  #
8
8
  NetSelection = Class.new YPetri::Agent::Selection
@@ -21,9 +21,9 @@ module YPetri::Agent::PetriNetRelated
21
21
  super
22
22
  end
23
23
 
24
- # Elements and selections:
24
+ # Nodes and selections:
25
25
  #
26
- delegate :place, :transition, :element,
26
+ delegate :place, :transition, :node,
27
27
  :nets, :places, :transitions,
28
28
  to: :world
29
29
 
@@ -74,17 +74,41 @@ module YPetri::Agent::PetriNetRelated
74
74
  world.Transition.send( :new, *ordered, **named, &block )
75
75
  end
76
76
 
77
+ # Place constructor: Creates a new place in the current world.
78
+ #
79
+ def Place( *ordered_args, **named_args, &block )
80
+ fail ArgumentError, "If block is given, :guard named argument " +
81
+ "must not be given!" if named_args.has? :guard if block
82
+ named_args.update( guard: block ) if block # use block as a guard
83
+ named_args.may_have :default_marking, syn!: :m!
84
+ named_args.may_have :marking, syn!: :m
85
+ world.Place.send( :new, *ordered_args, **named_args, &block )
86
+ end
87
+
88
+
89
+ # Assignment transition constructor: Creates a new assignment transition in
90
+ # the current world. Ordered arguments are collected as codomain. Domain key
91
+ # (+:domain) is optional. Assignment closure must be supplied in a block.
92
+ #
93
+ def AT( *codomain, **nn, &block )
94
+ fail ArgumentError, "Assignment transition constructor requires a block " +
95
+ "defining the assignment function!" unless block
96
+ world.Transition.send( :new,
97
+ codomain: codomain,
98
+ assignment: block,
99
+ **nn )
100
+ end
101
+
77
102
  # Timed transition constructor: Creates a new timed transition in the current
78
- # world. Rate closure has to be supplied as a block.
103
+ # world. Rate can be supplied either as +:rate+ named argument, or as a block.
104
+ # If none is supplied, rate argument defaults to 1.
79
105
  #
80
106
  def TT( *ordered, **named, &block )
81
107
  if named.has? :rate then
82
108
  fail ArgumentError, "Block must not be given if :rate named argument " +
83
109
  "is given!" if block
84
110
  else
85
- fail ArgumentError, "Timed transition constructor requires either " +
86
- "a :rate argument, or a block!" unless block
87
- named.update rate: block
111
+ named.update rate: block || 1 # default rate is 1
88
112
  end
89
113
  world.Transition.send( :new, *ordered, **named )
90
114
  end
@@ -101,7 +125,7 @@ module YPetri::Agent::PetriNetRelated
101
125
  args.update domain: nn.delete( :domain ) if nn.has? :domain
102
126
  else
103
127
  fail ArgumentError, "There must not be any ordered arguments if " +
104
- "named argument :domain is given!" unless domain.empty?
128
+ "named argument :domain is given!" if nn.has? :domain
105
129
  args.update domain: domain
106
130
  end
107
131
  args.update rate: nn.delete( :rate ) if nn.has? :rate, syn!: :rate_closure
@@ -148,4 +172,4 @@ module YPetri::Agent::PetriNetRelated
148
172
  def net_point= id
149
173
  net_point_reset id
150
174
  end
151
- end # module YPetri::Agent::PetriNetRelated
175
+ end # module YPetri::Agent::PetriNetAspect
@@ -1,9 +1,9 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Agent instance methods related to simulation (initial marking collections,
4
- # clamp collections, initial marking collections, management of simulations...)
3
+ # Simulation aspect of +YPetri::Agent+: initial marking collections, clamp
4
+ # collections, initial marking collections, management of simulations...
5
5
  #
6
- module YPetri::Agent::SimulationRelated
6
+ module YPetri::Agent::SimulationAspect
7
7
  require_relative 'hash_key_pointer'
8
8
  require_relative 'selection'
9
9
 
@@ -118,9 +118,8 @@ module YPetri::Agent::SimulationRelated
118
118
  return nil
119
119
  end
120
120
 
121
- # Returns the simulation identified by the argument, or one at simulation
122
- # point, if no argument given. The simulation is identified in the same way
123
- # as for #simulation_point_to method.
121
+ # Returns the simulation identified by the argument. If no argument is given,
122
+ # returns the simulation at point.
124
123
  #
125
124
  def simulation *args
126
125
  return simulation_point.get if args.empty?
@@ -155,7 +154,7 @@ module YPetri::Agent::SimulationRelated
155
154
  end
156
155
  alias ssc simulation_settings_collection
157
156
 
158
- # FIXME: This is going to be tested
157
+ # FIXME: This is not tested yet.
159
158
 
160
159
  def clamp clamp_hash
161
160
  clamp_hash.each_pair do |place, clamp|
@@ -265,75 +264,91 @@ module YPetri::Agent::SimulationRelated
265
264
  # Plot the recording reduced into the given feature set.
266
265
  #
267
266
  def plot features
268
- ff = simulation.net.state.features( features )
267
+ ff = simulation.net.State.Features( features )
269
268
  simulation.recording.reduce_features( ff ).plot
270
269
  end
271
270
 
272
271
  # Plot system state history.
273
272
  #
274
- def plot_marking( place_ids=nil, except: [],
273
+ def plot_marking( places=nil, except: [],
275
274
  title: "State plot", ylabel: "Marking [µM]",
276
275
  **options )
277
276
  rec = simulation.recording
278
- pp = simulation.pp( place_ids ) - simulation.pp( except )
279
- rec.marking( pp ).plot( title: title, ylabel: ylabel, **options )
277
+ pp = simulation.pp( *places ) - simulation.Pp( except )
278
+ rec.Marking( pp ).plot( title: title, ylabel: ylabel, **options )
280
279
  end
281
280
  alias plot_state plot_marking
282
281
 
283
282
  # Plot flux history of TS transitions.
284
283
  #
285
- def plot_flux( transition_ids=nil, except: [],
284
+ def plot_flux( transitions=nil, except: [],
286
285
  title: "Flux plot", ylabel: "Flux [µM.s⁻¹]",
287
286
  **options )
288
287
  rec = simulation.recording
289
- tt = transition_ids.nil? ? simulation.TS_tt : transition_ids
290
- tt = simulation.TS_tt( tt )
291
- tt -= simulation.tt( except )
292
- rec.flux( tt ).plot( title: title, ylabel: ylabel, **options )
288
+ tt = simulation.TS_tt( *transitions ) - simulation.Tt( except )
289
+ rec.Flux( tt ).plot( title: title, ylabel: ylabel, **options )
293
290
  end
294
291
 
295
292
  # Plot firing history of tS transitions.
296
293
  #
297
- def plot_firing( transition_ids=nil, except: [],
294
+ def plot_firing( transitions=nil, except: [],
298
295
  title: "Firing plot", ylabel: "Firing [µM]",
299
296
  **options )
300
297
  rec = simulation.recording
301
- tt = transition_ids.nil? ? simulation.tS_tt : transition_ids
302
- tt = simulation.tS_tt( tt )
303
- tt -= simulation.tt( except )
304
- rec.firing( tt ).plot( title: title, ylabel: ylabel, **options )
298
+ tt = simulation.tS_tt( *transitions ) - simulation.Tt( except )
299
+ rec.Firing( tt ).plot( title: title, ylabel: ylabel, **options )
305
300
  end
306
301
 
307
302
  # Plot gradient history of selected places with respect to a set of T
308
303
  # transitions.
309
304
  #
310
- def plot_gradient( place_ids=nil, except: [], transitions: nil,
305
+ def plot_gradient( places=nil, except: [], transitions: nil,
311
306
  title: "Gradient plot", ylabel: "Gradient [µM.s⁻¹]",
312
307
  **options )
313
308
  rec = simulation.recording
314
- pp = simulation.pp( place_ids ) - simulation.ee( place_ids )
315
- tt = transitions.nil? ? simulation.T_tt : transitions
316
- tt = simulation.T_tt( tt )
317
- tt -= simulation.ee( except )
318
- rec.gradient( pp, transitions: tt )
309
+ pp = simulation.pp( *places ) - simulation.Nn( except )
310
+ tt = simulation.T_tt( *transitions ) - simulation.Nn( except )
311
+ rec.Gradient( pp, transitions: tt )
319
312
  .plot( title: title, ylabel: ylabel, **options )
320
313
  end
321
314
 
322
315
  # Plot delta history of selected places with respect to a set of transitions.
323
316
  #
324
- def plot_delta( place_ids=nil, except: [], transitions: nil,
317
+ def plot_delta( places=nil, except: [], transitions: nil,
325
318
  title: "Delta plot", ylabel: "Delta [µM]",
326
319
  **options )
327
320
  options.may_have :delta_time, syn!: :Δt
328
321
  rec = simulation.recording
329
- pp = simulation.pp( place_ids ) - simulation.ee( except )
330
- tt = transitions.nil? ? simulation.tt : transitions
331
- tt = simulation.tt( tt )
332
- tt -= simulation.ee( except )
333
- rec.delta( pp, transitions: tt, Δt: options[:delta_time] )
322
+ pp = simulation.pp( *places ) - simulation.Nn( except )
323
+ tt = simulation.tt( *transitions ) - simulation.Nn( except )
324
+ simulation.recording.Delta( pp, transitions: tt, Δt: options[:delta_time] )
334
325
  .plot( title: title, ylabel: ylabel, **options )
335
326
  end
336
327
 
328
+ # Save a file.
329
+ #
330
+ def save_file f, txt
331
+ File.open( f, 'w' ) { |f| f.write "txt" }
332
+ end
333
+
334
+ # Load a file
335
+ #
336
+ def load_file f
337
+ rr = []
338
+ CSV.parse( File.open( f ), headers: true ) { |row|
339
+ rr << row
340
+ }
341
+ r1 = rr.first.to_hash.with_keys { |k| eval k }.with_values { |v| eval v }
342
+ ff = world.net.State.Features( r1.keys[ 1..-1 ] )
343
+ dataset = ff.DataSet.new
344
+ rr.each { |row|
345
+ r = row.to_hash.with_keys { |k| eval k }.with_values { |v| eval v }
346
+ event = r.delete :event
347
+ dataset[ event ] = ff.r.values
348
+ }
349
+ return dataset
350
+ end
351
+
337
352
  # # Pretty print marking of the current simulation.
338
353
  # #
339
354
  # def marking
@@ -367,4 +382,4 @@ module YPetri::Agent::SimulationRelated
367
382
  # tt = transitions.nil? ? simulation.tt : transitions
368
383
  # simulation.delta( place_id, except: except, transitions: transitions )
369
384
  # end
370
- end # module YPetri::Agent::SimulationRelated
385
+ end # module YPetri::Agent::SimulationAspect
data/lib/y_petri/agent.rb CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  require_relative 'agent/selection'
4
4
  require_relative 'agent/hash_key_pointer'
5
- require_relative 'agent/petri_net_related'
6
- require_relative 'agent/simulation_related'
5
+ require_relative 'agent/petri_net_aspect'
6
+ require_relative 'agent/simulation_aspect'
7
7
 
8
- # Public command interface of YPetri.
8
+ # A dumb agent that represents and helps the user.
9
9
  #
10
10
  class YPetri::Agent
11
- PetriNetRelated # ★ means include
12
- SimulationRelated
11
+ PetriNetAspect # ★ means include
12
+ SimulationAspect
13
13
 
14
14
  attr_reader :world
15
15
 
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ # Guarded simulation mixin – not working yet.
4
+ #
5
+ module YPetri::Core::Guarded
6
+ # Guarded version of the method.
7
+ #
8
+ def increment_marking_vector( delta )
9
+ try "to update marking" do
10
+ super( note( "Δ state if tS transitions fire once",
11
+ is: Δ_if_tS_fire_once ) +
12
+ note( "Δ state if tsa transitions fire once",
13
+ is: Δ_if_tsa_fire_once ) )
14
+ end
15
+ end
16
+
17
+ # Guarded version of the method.
18
+ #
19
+ def A_all_fire!
20
+ try "to fire the assignment transitions" do
21
+ super
22
+ end
23
+ end
24
+ end # module YPetri::Core::Guarded
@@ -1,15 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Euler method.
3
+ # Euler method. Assumes that only T transitions are in the net.
4
4
  #
5
5
  module YPetri::Core::Timed::Euler
6
- # Name of this method.
7
- #
8
- def simulation_method
9
- :euler
10
- end
11
-
12
- # Computes Δ for the period of Δt.
6
+ # Computes Δ for the period of Δt. Since this method assumes that only
7
+ # timed transitions are in the net, delta state is computed simply bu
8
+ # multiplying the gradient by Δt.
13
9
  #
14
10
  def delta Δt
15
11
  gradient * Δt
@@ -2,18 +2,17 @@
2
2
 
3
3
  # Plain Gillespie algorithm.
4
4
  #
5
- # The characteristic of the Gillespie method is, that it does not work starting
6
- # from Δt towards Δstate. Instead, it makes a random choice weighted by the
7
- # transition propensities, and the random choice determines both the next timed
8
- # transition to fire, and the size of Δt to slice off from the time axis.
5
+ # The distinguishing quality of Gillespie method is, that it does not work from
6
+ # from Δt towards Δstate. Instead, it makes a random choice of the transition to
7
+ # fire (weighted by the transition propensities) and a random choice of Δt. Both
8
+ # next transition to fire, and the size of Δt to slice off from the time axis are
9
+ # thus stochastically determined.
9
10
  #
10
11
  module YPetri::Core::Timed::Gillespie
11
- attr_reader :rng
12
-
13
- # Gillespie method initialization.
12
+ # Returns a random number generator, only created once.
14
13
  #
15
- def initialize
16
- @rng = ::Random
14
+ def rng
15
+ @rng ||= ::Random
17
16
  end
18
17
 
19
18
  # Makes a stochastic number of Gillespie steps necessary to span the period Δt.
@@ -25,7 +24,7 @@ module YPetri::Core::Timed::Gillespie
25
24
  update_next_gillespie_time( propensities )
26
25
  until ( @next_gillespie_time > target_time )
27
26
  gillespie_step! propensities
28
- simulation.recorder.alert
27
+ simulation.recorder.alert!
29
28
  propensities = propensity_vector_TS.column_to_a
30
29
  update_next_gillespie_time( propensities )
31
30
  end
@@ -33,12 +32,6 @@ module YPetri::Core::Timed::Gillespie
33
32
  print '.'
34
33
  end
35
34
 
36
- # Name of this method.
37
- #
38
- def simulation_method
39
- :gillespie
40
- end
41
-
42
35
  # This method updates next firing time given propensities.
43
36
  #
44
37
  def update_next_gillespie_time( propensities )
@@ -57,7 +50,8 @@ module YPetri::Core::Timed::Gillespie
57
50
  #
58
51
  def gillespie_delta_time( propensities )
59
52
  sum = Σ propensities
60
- mean_period = 1 / sum
53
+ # mean_period = 1 / sum # TODO: This line seem to be useless
54
+ # Exponential distribution
61
55
  Distribution::Exponential.p_value( rng.rand, sum )
62
56
  end
63
57
 
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ # Timed simulation core.
4
+ #
5
+ module YPetri::Core::Timed
6
+ require_relative 'euler'
7
+ require_relative 'pseudo_euler' # t transitions firing after each step
8
+ require_relative 'quasi_euler' # t transitions firing after each time tick
9
+ require_relative 'gillespie'
10
+ require_relative 'runge_kutta'
11
+
12
+ module Methods
13
+ def method_init
14
+ extend case simulation_method
15
+ when :euler then Euler
16
+ when :pseudo_euler then PseudoEuler
17
+ when :quasi_euler then QuasiEuler
18
+ when :gillespie then Gillespie
19
+ when :runge_kutta then RungeKutta
20
+ else fail TypeError, "Unknown timed simulation method: #{method}!" end
21
+ end
22
+ end
23
+ end
@@ -1,29 +1,26 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Euler method with timeless transitions firing after each step.
3
+ # Adaptation of Euler method for the systems possibly with timeless transitions
4
+ # and assignment transitions.
4
5
  #
5
6
  module YPetri::Core::Timed::PseudoEuler
6
- include YPetri::Core::Timed::Euler
7
-
8
- # Name of this method.
9
- #
10
- def simulation_method
11
- :pseudo_euler
12
- end
13
-
14
- # Computes Δ for the period of Δt.
7
+ # Computes Δ for the period of Δt. Its result is a sum of the contribution of
8
+ # timed transitions over the period Δt and the contribution of timeless
9
+ # transitions as if each fired once.
15
10
  #
16
11
  def delta Δt
17
- super + delta_timeless
12
+ gradient * Δt + delta_timeless
18
13
  end
19
14
  alias Δ delta
20
15
 
21
- # Makes a single step by Δt.
16
+ # Makes a single step by Δt. Computes system delta, increments marking vector
17
+ # by it. On top of that, fires all A transitions, increments the simulation
18
+ # time and alerts the sampler that the system has changed.
22
19
  #
23
20
  def step! Δt=simulation.step
24
21
  increment_marking_vector Δ( Δt )
25
22
  assignment_transitions_all_fire!
26
23
  simulation.increment_time! Δt
27
- alert
24
+ alert! # alerts the sampler that the system has changed
28
25
  end
29
26
  end # YPetri::Core::Timed::PseudoEuler
@@ -1,20 +1,21 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Euler method with timeless transitions firing every time tick.
3
+ # Adaptation of Euler method for the systems possibly with timeless transitions
4
+ # and assignment transitions. Unlike +pseudo_euler+, which fires every step,
5
+ # +quasi_euler+ fires every time tick. Not implemented yet.
4
6
  #
5
7
  module YPetri::Core::Timed::QuasiEuler
6
- include YPetri::Core::Timed::Euler
7
-
8
- # Name of this method.
8
+ # Computes Δ for the period of Δt. Not mplemented yet.
9
9
  #
10
- def simulation_method
11
- :quasi_euler
10
+ def delta Δt
11
+ fail NotImplementedError, "QuasiEuler not implemented yet!"
12
12
  end
13
13
 
14
- # Makes a single step by Δt.
14
+
15
+ # Makes a single step by Δt. Not implemented yet.
15
16
  #
16
17
  def step! Δt=simulation.step_size
17
- fail NotImplementedError
18
+ fail NotImplementedError, "QuasiEuler not implemented yet!"
18
19
  # Now one would have to compare whichever comes first, time tick or the
19
20
  # end of Δt, and then again and again, until Δt is fired...
20
21
  end
@@ -1,22 +1,14 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Gillespie method.
3
+ # Runge-Kutta method. Like vanilla Euler method, assumes that only T transitions are in the net.
4
4
  #
5
- module YPetri::Core::Timed::Euler
6
- # Name of this method.
7
- #
8
- def simulation_method
9
- :runge_kutta
5
+ module YPetri::Core::Timed::RungeKutta
6
+ def delta Δt
7
+ fail NotImplementedError, "RungeKutta not implemented yet!"
8
+ # Of course, the following line is from Euler method.
9
+ # The formula of Runge-Kutta is more complicated.
10
+ #
11
+ gradient * Δt
10
12
  end
11
-
12
- # FIXME
13
-
14
- # This is from Euler:
15
-
16
- # # Computes Δ for the period of Δt.
17
- # #
18
- # def delta Δt
19
- # gradient * Δt
20
- # end
21
- # alias Δ delta
22
- end # YPetri::Core::Timed::Euler
13
+ alias Δ delta
14
+ end # YPetri::Core::Timed::RungeKutta
@@ -2,18 +2,10 @@
2
2
 
3
3
  # Timed simulation core.
4
4
  #
5
- class YPetri::Core::Timed < YPetri::Core
6
- # Euler method.
7
- require_relative 'timed/euler'
8
- # Euler with timeless transitions firing after each step.
9
- require_relative 'timed/pseudo_euler'
10
- # Euler with timeless transitions firing each time tick.
11
- require_relative 'timed/quasi_euler'
12
- # Gillespie stochastic method.
13
- require_relative 'timed/gillespie'
14
- # Runge-Kutta fifth-order method.
15
- require_relative 'timed/runge_kutta'
16
-
5
+ module YPetri::Core::Timed
6
+ require_relative 'timed/methods'
7
+ Methods
8
+
17
9
  # Makes a single step by Δt.
18
10
  #
19
11
  def step! Δt=simulation.step
@@ -57,9 +49,9 @@ class YPetri::Core::Timed < YPetri::Core
57
49
  simulation.TS_rate_closure.call
58
50
  end
59
51
  alias propensity_vector_TS flux_vector_TS
60
- end # class YPetri::Core::Timed
52
+ end # module YPetri::Core::Timed
61
53
 
62
- # In general, it is not required that all net elements are simulated with the
54
+ # In general, it is not required that all net nodes are simulated with the
63
55
  # same method. Practically, ODE systems have many good simulation methods
64
56
  # available.
65
57
  #
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ # Timed simulation core.
4
+ #
5
+ module YPetri::Core::Timeless
6
+ require_relative 'pseudo_euler'
7
+
8
+ module Methods
9
+ def method_init
10
+ extend case simulation_method
11
+ when :pseudo_euler then PseudoEuler
12
+ else fail TypeError, "Unknown timeless simulation method: #{method}!" end
13
+ end
14
+ end
15
+ end
@@ -1,18 +1,14 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Implicit Euler for timeless nets. Simply, timeless transitions
4
- # fire simultaneously, after which A transitions (if any) fire.
3
+ # Implicit Euler for timeless nets.
5
4
  #
6
5
  module YPetri::Core::Timeless::PseudoEuler
7
- # Name of this method.
6
+ # Method #step! for timeless +pseudo_euler+ method. Simply, timeless
7
+ # transitions fire simultaneously, after which, A transitions (if any) fire.
8
8
  #
9
- def simulation_method
10
- :pseudo_euler
11
- end
12
-
13
9
  def step!
14
10
  increment_marking_vector Δ
15
11
  assignment_transitions_all_fire!
16
- alert
12
+ alert!
17
13
  end
18
14
  end # module YPetri::Core::Timeless::PseudoEuler
@@ -1,15 +1,20 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Timeless simulation core.
3
+ # Timeless simulator mixin.
4
4
  #
5
- class YPetri::Core::Timeless < YPetri::Core
6
- require_relative 'timeless/pseudo_euler'
5
+ module YPetri::Core::Timeless
6
+ require_relative 'timeless/methods'
7
+ ★ Methods
7
8
 
9
+ # Makes a single step.
10
+ #
8
11
  def delta
9
12
  delta_timeless
10
13
  end
11
14
 
15
+ # Computes the system state delta.
16
+ #
12
17
  def Δ
13
18
  delta
14
19
  end
15
- end # class YPetri::Core::Timeless
20
+ end # module YPetri::Core::Timeless