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.
- 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
|