y_petri 2.2.4 → 2.3.2
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 +4 -4
- data/LICENSE.txt +675 -0
- data/README.md +6 -3
- data/Rakefile +1 -1
- data/lib/y_petri/agent/{petri_net_related.rb → petri_net_aspect.rb} +34 -10
- data/lib/y_petri/agent/{simulation_related.rb → simulation_aspect.rb} +49 -34
- data/lib/y_petri/agent.rb +5 -5
- data/lib/y_petri/core/guarded.rb +24 -0
- data/lib/y_petri/core/timed/euler.rb +4 -8
- data/lib/y_petri/core/timed/gillespie.rb +11 -17
- data/lib/y_petri/core/timed/methods.rb +23 -0
- data/lib/y_petri/core/timed/pseudo_euler.rb +10 -13
- data/lib/y_petri/core/timed/quasi_euler.rb +9 -8
- data/lib/y_petri/core/timed/runge_kutta.rb +10 -18
- data/lib/y_petri/core/timed.rb +6 -14
- data/lib/y_petri/core/timeless/methods.rb +15 -0
- data/lib/y_petri/core/timeless/pseudo_euler.rb +4 -8
- data/lib/y_petri/core/timeless.rb +9 -4
- data/lib/y_petri/core.rb +44 -42
- data/lib/y_petri/net/data_set.rb +246 -142
- data/lib/y_petri/net/node_access.rb +282 -0
- data/lib/y_petri/net/own_state.rb +14 -4
- data/lib/y_petri/net/state/feature/assignment.rb +123 -0
- data/lib/y_petri/net/state/feature/delta.rb +55 -35
- data/lib/y_petri/net/state/feature/firing.rb +68 -25
- data/lib/y_petri/net/state/feature/flux.rb +9 -2
- data/lib/y_petri/net/state/feature/gradient.rb +36 -19
- data/lib/y_petri/net/state/feature/marking.rb +10 -5
- data/lib/y_petri/net/state/feature.rb +105 -11
- data/lib/y_petri/net/state/features/record.rb +144 -99
- data/lib/y_petri/net/state/features.rb +327 -200
- data/lib/y_petri/net/state.rb +48 -82
- data/lib/y_petri/net/visualization.rb +1 -1
- data/lib/y_petri/net.rb +62 -47
- data/lib/y_petri/place/arcs.rb +44 -0
- data/lib/y_petri/place/features.rb +115 -0
- data/lib/y_petri/place.rb +62 -29
- data/lib/y_petri/simulation/dependency.rb +31 -67
- data/lib/y_petri/simulation/feature_set.rb +1 -1
- data/lib/y_petri/simulation/initial_marking/access.rb +42 -26
- data/lib/y_petri/simulation/marking_clamps/access.rb +22 -17
- data/lib/y_petri/simulation/marking_clamps.rb +0 -2
- data/lib/y_petri/simulation/marking_vector/access.rb +102 -40
- data/lib/y_petri/simulation/marking_vector.rb +35 -37
- data/lib/y_petri/simulation/matrix.rb +1 -1
- data/lib/y_petri/simulation/node_representation.rb +25 -0
- data/lib/y_petri/simulation/nodes/access.rb +78 -0
- data/lib/y_petri/simulation/{elements.rb → nodes.rb} +14 -13
- data/lib/y_petri/simulation/place_mapping.rb +2 -2
- data/lib/y_petri/simulation/place_representation.rb +8 -7
- data/lib/y_petri/simulation/places/access.rb +89 -70
- data/lib/y_petri/simulation/places/free.rb +1 -1
- data/lib/y_petri/simulation/places/types.rb +20 -22
- data/lib/y_petri/simulation/places.rb +23 -18
- data/lib/y_petri/simulation/recorder.rb +23 -18
- data/lib/y_petri/simulation/timed/recorder.rb +19 -11
- data/lib/y_petri/simulation/timed.rb +93 -29
- data/lib/y_petri/simulation/timeless/recorder.rb +11 -6
- data/lib/y_petri/simulation/timeless.rb +13 -3
- data/lib/y_petri/simulation/transition_representation/A.rb +24 -4
- data/lib/y_petri/simulation/transition_representation/S.rb +11 -1
- data/lib/y_petri/simulation/transition_representation/T.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/Ts.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/a.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/s.rb +12 -1
- data/lib/y_petri/simulation/transition_representation/t.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/tS.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/ts.rb +1 -1
- data/lib/y_petri/simulation/transition_representation/types.rb +1 -1
- data/lib/y_petri/simulation/transition_representation.rb +4 -11
- data/lib/y_petri/simulation/transitions/A.rb +17 -2
- data/lib/y_petri/simulation/transitions/S.rb +1 -1
- data/lib/y_petri/simulation/transitions/T.rb +1 -1
- data/lib/y_petri/simulation/transitions/Ts.rb +6 -5
- data/lib/y_petri/simulation/transitions/a.rb +1 -1
- data/lib/y_petri/simulation/transitions/access.rb +195 -168
- data/lib/y_petri/simulation/transitions/s.rb +1 -1
- data/lib/y_petri/simulation/transitions/t.rb +1 -1
- data/lib/y_petri/simulation/transitions/tS.rb +1 -1
- data/lib/y_petri/simulation/transitions/ts.rb +1 -1
- data/lib/y_petri/simulation/transitions/types.rb +1 -1
- data/lib/y_petri/simulation/transitions.rb +5 -7
- data/lib/y_petri/simulation.rb +84 -90
- data/lib/y_petri/transition/A.rb +8 -2
- data/lib/y_petri/transition/T.rb +25 -2
- data/lib/y_petri/transition/arcs.rb +19 -3
- data/lib/y_petri/transition/construction_convenience.rb +11 -10
- data/lib/y_petri/transition/t.rb +14 -1
- data/lib/y_petri/transition/types.rb +6 -1
- data/lib/y_petri/transition.rb +9 -12
- data/lib/y_petri/version.rb +1 -1
- data/lib/y_petri/world/dependency.rb +3 -3
- data/lib/y_petri/world/{petri_net_related.rb → petri_net_aspect.rb} +4 -4
- data/lib/y_petri/world/simulation_aspect.rb +352 -0
- data/lib/y_petri/world.rb +4 -4
- data/lib/y_petri.rb +1 -1
- data/test/agent_test.rb +2 -1
- data/test/examples/demonstrator.rb +4 -1
- data/test/examples/demonstrator_2.rb +5 -0
- data/test/examples/demonstrator_4.rb +6 -5
- data/test/examples/example_2.rb +2 -0
- data/test/examples/manual_examples.rb +4 -4
- data/test/net_test.rb +457 -54
- data/test/place_test.rb +11 -7
- data/test/simulation_test.rb +358 -331
- data/test/transition_test.rb +11 -10
- data/test/world_test.rb +2 -0
- data/test/y_petri_test.rb +2 -1
- data/y_petri.gemspec +24 -18
- metadata +71 -17
- data/LICENSE +0 -22
- data/lib/y_petri/net/element_access.rb +0 -239
- data/lib/y_petri/simulation/element_representation.rb +0 -20
- data/lib/y_petri/simulation/elements/access.rb +0 -57
- data/lib/y_petri/transition/type.rb +0 -103
- data/lib/y_petri/transition/type_information.rb +0 -103
- 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
|
4
|
-
|
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_ (
|
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,8 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
#
|
3
|
+
# Petri net aspect of +YPetri::Agent+.
|
4
4
|
#
|
5
|
-
module YPetri::Agent::
|
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
|
-
#
|
24
|
+
# Nodes and selections:
|
25
25
|
#
|
26
|
-
delegate :place, :transition, :
|
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
|
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
|
-
|
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!"
|
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::
|
175
|
+
end # module YPetri::Agent::PetriNetAspect
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
3
|
+
# Simulation aspect of +YPetri::Agent+: initial marking collections, clamp
|
4
|
+
# collections, initial marking collections, management of simulations...
|
5
5
|
#
|
6
|
-
module YPetri::Agent::
|
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
|
122
|
-
#
|
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
|
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.
|
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(
|
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(
|
279
|
-
rec.
|
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(
|
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 =
|
290
|
-
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(
|
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 =
|
302
|
-
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(
|
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(
|
315
|
-
tt =
|
316
|
-
|
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(
|
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(
|
330
|
-
tt =
|
331
|
-
|
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::
|
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/
|
6
|
-
require_relative 'agent/
|
5
|
+
require_relative 'agent/petri_net_aspect'
|
6
|
+
require_relative 'agent/simulation_aspect'
|
7
7
|
|
8
|
-
#
|
8
|
+
# A dumb agent that represents and helps the user.
|
9
9
|
#
|
10
10
|
class YPetri::Agent
|
11
|
-
★
|
12
|
-
★
|
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
|
-
#
|
7
|
-
#
|
8
|
-
|
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
|
6
|
-
# from Δt towards Δstate. Instead, it makes a random choice
|
7
|
-
# transition propensities
|
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
|
-
|
12
|
-
|
13
|
-
# Gillespie method initialization.
|
12
|
+
# Returns a random number generator, only created once.
|
14
13
|
#
|
15
|
-
def
|
16
|
-
@rng
|
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
|
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
|
-
|
7
|
-
|
8
|
-
#
|
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
|
-
|
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
|
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
|
-
|
7
|
-
|
8
|
-
# Name of this method.
|
8
|
+
# Computes Δ for the period of Δt. Not mplemented yet.
|
9
9
|
#
|
10
|
-
def
|
11
|
-
|
10
|
+
def delta Δt
|
11
|
+
fail NotImplementedError, "QuasiEuler not implemented yet!"
|
12
12
|
end
|
13
13
|
|
14
|
-
|
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
|
-
#
|
3
|
+
# Runge-Kutta method. Like vanilla Euler method, assumes that only T transitions are in the net.
|
4
4
|
#
|
5
|
-
module YPetri::Core::Timed::
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
data/lib/y_petri/core/timed.rb
CHANGED
@@ -2,18 +2,10 @@
|
|
2
2
|
|
3
3
|
# Timed simulation core.
|
4
4
|
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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 #
|
52
|
+
end # module YPetri::Core::Timed
|
61
53
|
|
62
|
-
# In general, it is not required that all net
|
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.
|
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
|
-
#
|
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
|
3
|
+
# Timeless simulator mixin.
|
4
4
|
#
|
5
|
-
|
6
|
-
require_relative 'timeless/
|
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 #
|
20
|
+
end # module YPetri::Core::Timeless
|