y_petri 2.3.11 → 2.3.12

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: 213efc795950a5d200a6b5c10fe3150dddf4940b
4
- data.tar.gz: 6c1a54e4526c7f19ea63dc7faad780526e2d3ee2
3
+ metadata.gz: 3fe2aaae8033f7806b851cd4293f555d15beb5a5
4
+ data.tar.gz: 79271fa571273448d6716b547785f66805b5d5b4
5
5
  SHA512:
6
- metadata.gz: 60800f142748c833d2298583393f3790532d56bf294779d02a6e6b6991409bdc12b584bf64ec286868012d3b4d25e0a18cc8a5ac170359ab4c00ca7c703fdf52
7
- data.tar.gz: aacfcbc2bbba5c262c5e2cab747a4fe093d047b02a65781709eec758a30b5bc9222dcd0a6874afdf1041d1a8d3f9d9e143fe0bd80f26361df6f5cd4b64e9182e
6
+ metadata.gz: 14a6aba15f89a662ee2e13e16dc09695c1d00ccbe60ce7f969b9ae2a348f9bc8c98f51a2090643671b568d06f36419d162dda8ef5005fd34f014ec28aa75a855
7
+ data.tar.gz: 66681f89b12fc840eabc2d225af8e137492870c61c8d844b8fcb73cd78ef712bfe46c497882be534a98e5287bb76e7aa97a726f032bd16346cb79a735d4069e9
@@ -1,9 +1,9 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Adaptation of Euler method for the systems possibly with timeless transitions
4
- # and assignment transitions.
3
+ # Basic Petri net execution method for timed and hybrid nets. Works also for
4
+ # timeless nets, but for those, Core::Timeless::Basic is slightly more efficient.
5
5
  #
6
- module YPetri::Core::Timed::PseudoEuler
6
+ module YPetri::Core::Timed::Basic
7
7
  # Computes Δ for the period of Δt. Its result is a sum of the contribution of
8
8
  # timed transitions over the period Δt and the contribution of timeless
9
9
  # transitions as if each fired once.
@@ -23,4 +23,4 @@ module YPetri::Core::Timed::PseudoEuler
23
23
  simulation.increment_time! Δt
24
24
  alert! # alerts the sampler that the system has changed
25
25
  end
26
- end # YPetri::Core::Timed::PseudoEuler
26
+ end # YPetri::Core::Timed::Basic
@@ -4,9 +4,7 @@
4
4
  #
5
5
  module YPetri::Core::Timed::RungeKutta
6
6
  def delta Δt
7
- fail NotImplementedError, "RungeKutta not implemented yet!"
8
-
9
- # f = simulation.method :gradient, parameter: :state
7
+ # The f below is from the equation state' = f( state )
10
8
  f = lambda { |mv| # mv is the marking vector of the free places
11
9
  result = "make hash from free places of the simulation to zeros"
12
10
  nonstoichiometric_transitions.each { |t|
@@ -4,7 +4,7 @@
4
4
  # and assignment transitions. Unlike +pseudo_euler+, which fires every step,
5
5
  # +quasi_euler+ fires every time tick. Not implemented yet.
6
6
  #
7
- module YPetri::Core::Timed::QuasiEuler
7
+ module YPetri::Core::Timed::Ticked
8
8
  # Computes Δ for the period of Δt. Not mplemented yet.
9
9
  #
10
10
  def delta Δt
@@ -19,4 +19,4 @@ module YPetri::Core::Timed::QuasiEuler
19
19
  # Now one would have to compare whichever comes first, time tick or the
20
20
  # end of Δt, and then again and again, until Δt is fired...
21
21
  end
22
- end # YPetri::Core::Timed::QuasiEuler
22
+ end # YPetri::Core::Timed::Ticked
@@ -1,10 +1,34 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Timed simulation core.
3
+ # Timed simulation core. Knows several simulation methods applicable to
4
+ # timed nets.
4
5
  #
5
- module YPetri::Core::Timed
6
- require_relative 'timed/methods'
7
- ★ Methods
6
+ class YPetri::Core::Timed
7
+ YPetri::Core
8
+
9
+ require_relative 'timed/basic'
10
+ require_relative 'timed/ticked' #
11
+ require_relative 'timed/euler'
12
+ require_relative 'timed/runge_kutta'
13
+ require_relative 'timed/gillespie'
14
+
15
+ METHODS = {
16
+ basic: Basic, # simple PN execution, timeless tt fire after each step
17
+ ticked: Ticked, # like basic, but timeless tt fire at every time tick
18
+ euler: Euler, # for timed nets only
19
+ runge_kutta: RungeKutta, # for timed nets only
20
+ gillespie: Gillespie # for timed nets only
21
+ }
22
+
23
+ def initialize **named_args
24
+ super
25
+ extend METHODS.fetch simulation_method
26
+ # look in the Core#initialize method for the closures and parameters
27
+ # and such. Here, we could define:
28
+ @Ts_gradient_closure = simulation.Ts_gradient_closure
29
+ # which would remind us that this machine needs to be
30
+ # actually defined internal to Core instance
31
+ end
8
32
 
9
33
  # Makes a single step by Δt.
10
34
  #
@@ -25,6 +49,8 @@ module YPetri::Core::Timed
25
49
  #
26
50
  def gradient_Ts
27
51
  simulation.Ts_gradient_closure.call
52
+ # this could be
53
+ # @Ts_gradient_closure.call
28
54
  end
29
55
 
30
56
  # Gradient contribution by TS transitions.
@@ -51,11 +77,9 @@ module YPetri::Core::Timed
51
77
  alias propensity_vector_TS flux_vector_TS
52
78
  end # module YPetri::Core::Timed
53
79
 
54
- # In general, it is not required that all net nodes are simulated with the
55
- # same method. Practically, ODE systems have many good simulation methods
56
- # available.
80
+ # Textbook simulation methods ODE systems have many good simulation methods available.
57
81
  #
58
- # (1) ᴍ(t) = ϝ f(ᴍ, t).dt, where f(ᴍ, t) is a known function.
82
+ # (1) mv' = ϝ f(mv, t).dt, where f(m, t) is a known function.
59
83
  #
60
84
  # Many of these methods depend on the Jacobian, but that may not be available
61
85
  # for some places. Therefore, the places, whose marking defines the system
@@ -66,3 +90,5 @@ end # module YPetri::Core::Timed
66
90
  # If we apply the definition of "causal orientation" on A and E places, then it
67
91
  # can be said, that only the transitions causally oriented towards "A" places
68
92
  # are allowed for compliance with the equation (1).
93
+
94
+ # In general, it is not required that all net nodes are simulated with the same method.
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ # The basic simulation method in YPetri is simple Petri net (PN) execution. While
4
+ # in principle applicable to any PN type, it can be made slightly more efficient
5
+ # if it is known in advance that no no timed transitions will be in the net.
6
+ #
7
+ module YPetri::Core::Timeless::Basic
8
+ # Peforms a single step of the basic method.
9
+ #
10
+ def step!
11
+ # Compute the sum of the contribution of ts and tS transitions, and
12
+ # increment the free marking vector by it.
13
+ increment_free_vector by: delta_ts + delta_tS
14
+ # Fire all the assignment transitions in their order.
15
+ fire_all_assignment_transitions!
16
+ # before: assignment_transitions_all_fire!
17
+ # Alert the recorder(s) that the system has changed.
18
+ alert!
19
+ end
20
+ end # module YPetri::Core::Timeless::Basic
@@ -1,15 +1,27 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Timeless simulator mixin.
3
+ # Timeless simulator core. Knows thus far only one, but potentially several
4
+ # methods applicable to timeless systems simulations.
4
5
  #
5
- module YPetri::Core::Timeless
6
- require_relative 'timeless/methods'
7
- ★ Methods
6
+ class YPetri::Core::Timeless
7
+ YPetri::Core
8
+
9
+ require_relative 'timeless/basic'
10
+
11
+ METHODS = { basic: Basic } # basic PN execution
12
+ # Note: the reason why Timeless core has distinct basic method is because
13
+ # without having to consider timed transitions, it can be made simpler.
8
14
 
9
- # Makes a single step.
15
+ def initialize **named_args
16
+ super
17
+ extend METHODS.fetch simulation_method
18
+ end
19
+
20
+ # Computes the system state delta.
10
21
  #
11
22
  def delta
12
- delta_timeless
23
+ delta_timeless # this method was taken from core.rb
24
+ # delta_ts + delta_tS # this is the contents of delta_timeless method
13
25
  end
14
26
 
15
27
  # Computes the system state delta.
data/lib/y_petri/core.rb CHANGED
@@ -1,83 +1,62 @@
1
1
  # encoding: utf-8
2
2
 
3
- # This class represents a simulator.
3
+ # This module represents a simulation core (execution machine), which can be
4
+ # either timed (class Core::Timed) or timeless (class Core::Timeless).
4
5
  #
5
- class YPetri::Core
6
- # TODO: currently, Core and Simulation classes are tightly coupled.
7
- # each simulation has just one core, and that core looks directly
8
- # into the simulation's state. What needs to be done is a simulation
9
- # that at least hints the process of core recruitment for the requested
10
- # operation (be it step, step backwards, run forward aso.) and then
11
- # imprints the core with its current marking vector, tells the core
12
- # what to do, and then reads the result and updates its marking vector
13
- # accordingly. There are multiple possibilities, such as constructing
14
- # a new core for each operation, or keeping the same core for all the
15
- # operations using a given method. A simulation method (like euler,
16
- # gillespie, or runge-kutta) should be associated not so much with
17
- # the simulation object, as it should be associated with the core
18
- # object. A core object should be more or less one-trick pony. While
19
- # later, it is possible for a simulation to have broader simulation
20
- # strategy, or "method" in the broader sense. But simulation should
21
- # also avoid doing too much, because above it, there is Agent class,
22
- # and this class can be taught to do the more complicated things
23
- # such as parameter optimization or computation of control coefficients
24
- # and such. It is also possible to construct more specialized agent-like
25
- # classes for these more specialized tasks, since the main purpose
26
- # of Agent class, as I saw it, was to represent the user (represent
27
- # what the user means), to provide the user interface.
28
-
6
+ module YPetri::Core
7
+ YPetri::Simulation::Dependency # dependency stays for now
8
+
29
9
  require_relative 'core/timed'
30
10
  require_relative 'core/timeless'
31
- require_relative 'core/guarded'
32
11
 
33
- YPetri::Simulation::Dependency
12
+ DEFAULT_METHOD = :basic
34
13
 
35
- DEFAULT_METHOD = :pseudo_euler
14
+ # I'm doing it this way in order to gradually begin decoupling in my mind
15
+ # core from simulation. The constructed core will have to be assigned the
16
+ # simulation object on which it will depend before core is made completely
17
+ # independend on simulation. (Not gonna happen any soon.)
18
+ #
19
+ attr_reader :simulation # just a remark:
20
+ attr_reader :simulation_method # "reader" is "selector" in Landin's language
36
21
 
37
- class << self
38
- # Timed subclass of self.
39
- #
40
- def timed
41
- Class.new self do
42
- include Timed
43
- def timed?; true end
44
- def timeless?; false end
45
- end
46
- end
47
-
48
- # Timeless subclass of self.
49
- #
50
- def timeless
51
- Class.new self do
52
- include Timeless
53
- def timed?; false end
54
- def timeless?; true end
55
- end
56
- end
57
-
58
- # Vanilla simulator is not guarded.
22
+ def initialize simulation: nil, method: nil, guarded: false, **named_args
23
+ @simulation = simulation or fail ArgumentError, "Core requires simulation!"
24
+ @simulation_method = method || DEFAULT_METHOD
25
+
26
+ if guarded then # TODO: Guarded is unfinished business.
27
+ fail NotImplementedMethod, "Guarded core is not implemented yet!"
28
+ require_relative 'core/guarded' # TODO: Should be replaced with autoload.
29
+ else @guarded = false end
30
+
31
+ # Dependent on Simulation, this machine returns "delta contribution for ts
32
+ # (timeless nonstoichiometric) transitions", which smells like a vector of
33
+ # size corresponding to the number of free places.
59
34
  #
60
- def guarded?; false end
35
+ @delta_closure_for_ts_transitions = simulation.ts_delta_closure
61
36
 
62
- # Guarded subclass of self (not working yet).
37
+ # This one is slightly different in that it returns so-called "firing vector",
38
+ # from which delta vector is computed by multiplying it with tS stoichiometry
39
+ # matrix.
63
40
  #
64
- def guarded
65
- Class.new self do
66
- include Guarded
67
- def guarded?; true end
68
- end
69
- end
70
- end
41
+ @firing_closure_for_tS_transitions = simulation.tS_firing_closure
71
42
 
72
- attr_reader :simulation_method
43
+ # This machine is special in that it directly modifies the marking vector,
44
+ # firing the assignment transitions one by one (or so I think).
45
+ #
46
+ @assignment_closure_for_A_transitions = simulation.A_direct_assignment_closure
73
47
 
74
- def initialize method: nil, guarded: false, **named_args
75
- @simulation_method = method || DEFAULT_METHOD
76
- method_init # defined in Timed::Methods and Timeless::Methods
48
+ # We're gonna change all of the above. The marking vectors will be owned by
49
+ # the core now. Machines will be wired only inside the core.
77
50
  end
78
51
 
79
- delegate :simulation,
80
- :timed?,
52
+ # TODO: this delegation below is not completely right.
53
+ # 1. There is no subclassing and Timed/Timeless module inclusion, so there
54
+ # is no need to delegate timed?/timeless? to the class, if only the modules
55
+ # provide those inquirer methods (predicates in Landin's language).
56
+ # 2. Same goes for guarded? predicate, which might be the business of
57
+ # Core::Guarded module (or not)
58
+ #
59
+ delegate :timed?,
81
60
  :timeless?,
82
61
  :guarded?,
83
62
  to: "self.class"
@@ -102,24 +81,71 @@ class YPetri::Core
102
81
  #
103
82
  def delta_ts
104
83
  simulation.ts_delta_closure.call
84
+ # @delta_closure_for_ts_transitions.call
105
85
  end
106
86
 
107
87
  # Firing vector of tS transitions.
108
88
  #
109
89
  def firing_vector_tS
110
90
  simulation.tS_firing_closure.call
91
+ # @firing_closure_for_tS_transitions.call
111
92
  end
112
93
 
113
94
  # Increments the marking vector by a given delta.
114
95
  #
115
96
  def increment_marking_vector( delta )
116
97
  print '.'
98
+ # TODO: From now on, this won't touch the simulation's property
99
+ # at all. It will be left to the simulation to ask for the results,
100
+ # or to rig the core to message back when done.
117
101
  simulation.increment_marking_vector_closure.( delta )
118
102
  end
119
103
 
120
- # Fires assignment transitions.
104
+ # Fires all the assignment transitions.
121
105
  #
122
- def assignment_transitions_all_fire!
106
+ def fire_all_assignment_transitions!
123
107
  simulation.A_direct_assignment_closure.call
108
+ # @assignment_closure_for_A_transitions.call
124
109
  end
125
- end # class YPetri::Core
110
+ alias assignment_transitions_all_fire! fire_all_assignment_transitions!
111
+ end # module YPetri::Core
112
+
113
+ # TODO: Decouple Core and Simulation classes. It still looks like one
114
+ # simulation will use only one core (or one for each type of simulation
115
+ # trick), but I don't want the core to be parametrized by a Simulation
116
+ # instance. There should be at least a hint of core recruitment, sending
117
+ # the state to the core, asking the core to perform its trick on it, and
118
+ # asking back the results (or rigging the core to send them back as soon
119
+ # as done). A core should be more or less a one-trick pony. But simulation
120
+ # should also avoid doing too much, because above it, other classes (Agent
121
+ # and co.) may exist, doing things like optimization, parameter inferences
122
+ # aso.
123
+
124
+ # TODO: Regarding guarded cores, many kinds of PNs prohibit places from
125
+ # acquiring negative marking, or impose other restrictions. If the system
126
+ # state somehow makes it out of this safe envelope, the transitions may
127
+ # start behaving unpredictably. So there is a question of who is responsible
128
+ # for keeping the system sane (in the safe state envelope). The simple thing
129
+ # is for the core not to test anything and leave it up to the user not to
130
+ # define systems that are not sane. Simple is good, but there must be agreement,
131
+ # a requirement that the system specification behaves. If there is no such
132
+ # agreement, the core has no excuse from the need to guard against transitions
133
+ # trying to fire when they should properly be disabled (at least not if the
134
+ # core knows that the PN in question is classical). I did not decide what exactly
135
+ # should happen if the sanity is broken (raise an error? warn and try minor
136
+ # repair measures yourself?), but something should.
137
+ #
138
+ # Another example, in chemical systems, negative markings (concentrations)
139
+ # also ordinarily make no sense. But insensitive combination of functions
140
+ # and simulation method may lead to unsafe state with relatively late detection
141
+ # of error, leaving the modeller wondering when exactly the system state went
142
+ # haywire. Again, I'm not sure how exactly should the guarded core react to
143
+ # the treat of insane situation, but it somehow should.
144
+ #
145
+ # I feel it is necessary for the core to have awareness of the quality of
146
+ # the momentary system's state (at least to be able to tell whether it's
147
+ # meaningful at all), because later I want to let the core choose between
148
+ # deterministic (continous) and stochastic (discrete, going quantum by
149
+ # quantum, or by several quanta, there is more than one stochastic discrete
150
+ # method in stock) methods for simulation of individual processes.
151
+
@@ -9,7 +9,7 @@ module YPetri
9
9
  Transition = Class.new
10
10
  Net = Class.new Module
11
11
  Simulation = Class.new
12
- Core = Class.new
12
+ Core = Module.new
13
13
  World = Class.new
14
14
  Agent = Class.new
15
15
  end # module YPetri
@@ -254,14 +254,15 @@ module YPetri::Simulation::Timed
254
254
  @time_unit = anything.class.one
255
255
  @initial_time, @target_time = time_unit * 0, time_unit * Float::INFINITY
256
256
  end
257
- init_core_and_recorder_subclasses
257
+ # Set up a parametrized subclas of the sampler for timed simulation.
258
+ param_class( { Recorder: Recorder }, with: { simulation: self } )
258
259
  reset_time!
259
260
  @step = settings[:step] || time_unit
260
261
  @default_sampling = settings[:sampling] || step
261
262
  @core = if @guarded then
262
- Core().guarded.new( method: method )
263
+ YPetri::Core::Timed.new( simulation: self, method: method, guarded: true )
263
264
  else
264
- Core().new( method: method )
265
+ YPetri::Core::Timed.new( simulation: self, method: method, guarded: false )
265
266
  end
266
267
  @recorder = if features_to_record then
267
268
  # we'll have to figure out features
@@ -277,13 +278,4 @@ module YPetri::Simulation::Timed
277
278
  Recorder().new( sampling: settings[:sampling] )
278
279
  end
279
280
  end
280
-
281
- # Sets up subclasses of +Core+ (the simulator) and +Recorder+ (the sampler)
282
- # for timed simulations.
283
- #
284
- def init_core_and_recorder_subclasses
285
- param_class( { Core: YPetri::Core.timed,
286
- Recorder: Recorder },
287
- with: { simulation: self } )
288
- end
289
281
  end # module YPetri::Simulation::Timed
@@ -2,36 +2,38 @@
2
2
 
3
3
  # A mixin for timeless simulations.
4
4
  #
5
- class YPetri::Simulation
6
- module Timeless
7
- require_relative 'timeless/recorder'
5
+ module YPetri::Simulation::Timeless
6
+ require_relative 'timeless/recorder'
8
7
 
9
- # False for timeless simulations.
10
- #
11
- def timed?
12
- false
13
- end
8
+ # False for timeless simulations.
9
+ #
10
+ def timed?
11
+ false
12
+ end
14
13
 
15
- # Changing the simulation method on the fly not supported.
16
- #
17
- def set_simulation_method
18
- fail NoMethodError, "Changing simulation method on the fly not supported!"
19
- end
14
+ # Changing the simulation method on the fly not supported.
15
+ #
16
+ def set_simulation_method
17
+ fail NoMethodError, "Changing simulation method on the fly not supported!"
18
+ end
20
19
 
21
- private
20
+ private
22
21
 
23
- # Initialization subroutine for timeless simulations. Sets up the
24
- # parametrized subclasses +@Core+ (the simulator) and +@Recorder+,
25
- # and initializes the +@recorder+ attribute.
26
- #
27
- def init **settings
28
- method = settings[:method] # the simulation method
29
- features_to_record = settings[:record]
30
- init_core_and_recorder_subclasses
22
+ # Initialization subroutine for timeless simulations. Sets up the
23
+ # parametrized subclasses +@Core+ (the simulator) and +@Recorder+,
24
+ # and initializes the +@recorder+ attribute.
25
+ #
26
+ def init **settings
27
+ method = settings[:method] # the simulation method
28
+ features_to_record = settings[:record]
29
+ # Sets up a parametrized subclass of the sampler for timeless simulation.
30
+ param_class( { Recorder: Recorder }, with: { simulation: self } )
31
31
  @core = if @guarded then
32
- Core().guarded.new( method: method )
32
+ YPetri::Core::Timeless
33
+ .new( simulation: self, method: method, guarded: true )
33
34
  else
34
- Core().new( method: method )
35
+ YPetri::Core::Timeless
36
+ .new( simulation: self, method: method, guarded: false )
35
37
  end
36
38
  @recorder = if features_to_record then
37
39
  # we'll have to figure out features
@@ -47,14 +49,4 @@ class YPetri::Simulation
47
49
  Recorder().new # init the recorder
48
50
  end
49
51
  end
50
-
51
- # Sets up subclasses of +Core+ (the simulator) and +Recorder+ (the sampler)
52
- # for timeless simulations.
53
- #
54
- def init_core_and_recorder_subclasses
55
- param_class( { Core: YPetri::Core.timeless,
56
- Recorder: Recorder },
57
- with: { simulation: self } )
58
- end
59
- end # module Timeless
60
- end # module YPetri::Simulation
52
+ end # module YPetri::Simulation::Timeless
@@ -42,7 +42,7 @@ class YPetri::Simulation
42
42
  ★ MarkingClamps::Access
43
43
  ★ MarkingVector::Access
44
44
 
45
- DEFAULT_SETTINGS = -> do { method: :pseudo_euler, guarded: false } end
45
+ DEFAULT_SETTINGS = -> do { method: :basic, guarded: false } end
46
46
 
47
47
  class << self
48
48
  alias __new__ new
@@ -1,4 +1,4 @@
1
1
  module YPetri
2
- VERSION = "2.3.11"
2
+ VERSION = "2.3.12"
3
3
  DEBUG = false
4
4
  end
@@ -123,7 +123,7 @@ require_relative '../lib/y_petri' # tested component itself
123
123
  # @sim.m.must_equal [1, 2]
124
124
  # @sim.p_m.must_equal( { A: 1, B: 2 } )
125
125
  # @sim.recording.must_equal( { 0 => [1, 2]} )
126
- # @sim.simulation_method.must_equal :pseudo_euler
126
+ # @sim.simulation_method.must_equal :basic
127
127
  # @sim.core.must_be_kind_of YPetri::Core
128
128
  # @sim.ts_tt.first.domain.must_equal []
129
129
  # @sim.send( :ts_transitions ).first.domain_access_code.must_equal ''
@@ -195,7 +195,7 @@ require_relative '../lib/y_petri' # tested component itself
195
195
 
196
196
  # it "should behave" do
197
197
  # @sim.timed?.must_equal true
198
- # @sim.simulation_method.must_equal :pseudo_euler
198
+ # @sim.simulation_method.must_equal :basic
199
199
  # @sim.Ts_tt.size.must_equal 1
200
200
  # @sim.send( :transitions ).Ts.first.gradient_closure.call.must_equal [1]
201
201
  # @sim.Ts_tt.first.codomain.names.must_equal [:A]
@@ -212,7 +212,7 @@ require_relative '../lib/y_petri' # tested component itself
212
212
 
213
213
  # it "should behave" do
214
214
  # @sim.send( :transitions ).Ts.first.codomain.names.must_equal [:A]
215
- # @sim.simulation_method.must_equal :pseudo_euler
215
+ # @sim.simulation_method.must_equal :basic
216
216
  # @sim.timed?.must_equal true
217
217
  # @sim.core.timed?.must_equal true
218
218
  # @sim.reset!
@@ -289,7 +289,7 @@ require_relative '../lib/y_petri' # tested component itself
289
289
  # it "should behave" do
290
290
  # s = simulation
291
291
  # assert ! s.timed?
292
- # s.core.must_be_kind_of YPetri::Core::Timeless::PseudoEuler
292
+ # s.core.ancestors.must_include YPetri::Core::Timeless::Basic
293
293
  # ds = s.recording
294
294
  # ds.size.must_equal 6
295
295
  # ds.events.must_equal [0, 1, 2, 3, 4, 5]
@@ -334,7 +334,7 @@ describe "timed simulation" do
334
334
  it "should behave" do
335
335
  places.map( &:marking ).must_equal [0.5, 0.5] # marking unaffected
336
336
  s = simulation
337
- s.settings.must_equal( { method: :pseudo_euler, guarded: false,
337
+ s.settings.must_equal( { method: :basic, guarded: false,
338
338
  step: 0.1, sampling: 5, time: 0..60 } )
339
339
  assert s.recording.to_csv.start_with?( ":event,:A,:B\n" +
340
340
  "0.0,0.5,0.5\n" +
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: y_petri
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.11
4
+ version: 2.3.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - boris
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-05 00:00:00.000000000 Z
11
+ date: 2015-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -145,15 +145,13 @@ files:
145
145
  - lib/y_petri/core.rb
146
146
  - lib/y_petri/core/guarded.rb
147
147
  - lib/y_petri/core/timed.rb
148
+ - lib/y_petri/core/timed/basic.rb
148
149
  - lib/y_petri/core/timed/euler.rb
149
150
  - lib/y_petri/core/timed/gillespie.rb
150
- - lib/y_petri/core/timed/methods.rb
151
- - lib/y_petri/core/timed/pseudo_euler.rb
152
- - lib/y_petri/core/timed/quasi_euler.rb
153
151
  - lib/y_petri/core/timed/runge_kutta.rb
152
+ - lib/y_petri/core/timed/ticked.rb
154
153
  - lib/y_petri/core/timeless.rb
155
- - lib/y_petri/core/timeless/methods.rb
156
- - lib/y_petri/core/timeless/pseudo_euler.rb
154
+ - lib/y_petri/core/timeless/basic.rb
157
155
  - lib/y_petri/dsl.rb
158
156
  - lib/y_petri/fixed_assets.rb
159
157
  - lib/y_petri/net.rb
@@ -1,23 +0,0 @@
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,15 +0,0 @@
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,14 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # Implicit Euler for timeless nets.
4
- #
5
- module YPetri::Core::Timeless::PseudoEuler
6
- # Method #step! for timeless +pseudo_euler+ method. Simply, timeless
7
- # transitions fire simultaneously, after which, A transitions (if any) fire.
8
- #
9
- def step!
10
- increment_marking_vector Δ
11
- assignment_transitions_all_fire!
12
- alert!
13
- end
14
- end # module YPetri::Core::Timeless::PseudoEuler