y_petri 2.0.15 → 2.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/y_petri/{manipulator → agent}/hash_key_pointer.rb +2 -2
- data/lib/y_petri/agent/petri_net_related.rb +115 -0
- data/lib/y_petri/{manipulator → agent}/selection.rb +2 -1
- data/lib/y_petri/{manipulator/simulation_related_methods.rb → agent/simulation_related.rb} +93 -110
- data/lib/y_petri/agent.rb +22 -0
- data/lib/y_petri/core/timed/euler.rb +20 -0
- data/lib/y_petri/core/timed/pseudo_euler.rb +31 -0
- data/lib/y_petri/core/timed/quasi_euler.rb +23 -0
- data/lib/y_petri/core/timed.rb +70 -0
- data/lib/y_petri/core/timeless/pseudo_euler.rb +20 -0
- data/lib/y_petri/core/timeless.rb +12 -0
- data/lib/y_petri/core.rb +100 -0
- data/lib/y_petri/dsl.rb +66 -0
- data/lib/y_petri/fixed_assets.rb +7 -0
- data/lib/y_petri/net/element_access.rb +239 -0
- data/lib/y_petri/net/state/feature/delta.rb +88 -0
- data/lib/y_petri/net/state/feature/firing.rb +57 -0
- data/lib/y_petri/net/state/feature/flux.rb +58 -0
- data/lib/y_petri/net/state/feature/gradient.rb +75 -0
- data/lib/y_petri/net/state/feature/marking.rb +62 -0
- data/lib/y_petri/net/state/feature.rb +79 -0
- data/lib/y_petri/net/state/features/dataset.rb +135 -0
- data/lib/y_petri/net/state/features/record.rb +50 -0
- data/lib/y_petri/net/state/features.rb +126 -0
- data/lib/y_petri/net/state.rb +121 -0
- data/lib/y_petri/net/timed.rb +8 -0
- data/lib/y_petri/net/visualization.rb +3 -3
- data/lib/y_petri/net.rb +73 -77
- data/lib/y_petri/place.rb +8 -3
- data/lib/y_petri/simulation/dependency.rb +107 -0
- data/lib/y_petri/simulation/element_representation.rb +20 -0
- data/lib/y_petri/simulation/elements/access.rb +57 -0
- data/lib/y_petri/simulation/elements.rb +45 -0
- data/lib/y_petri/simulation/feature_set.rb +21 -0
- data/lib/y_petri/simulation/initial_marking/access.rb +55 -0
- data/lib/y_petri/simulation/initial_marking.rb +15 -0
- data/lib/y_petri/simulation/marking_clamps/access.rb +34 -0
- data/lib/y_petri/simulation/marking_clamps.rb +18 -0
- data/lib/y_petri/simulation/marking_vector/access.rb +106 -0
- data/lib/y_petri/simulation/marking_vector.rb +156 -0
- data/lib/y_petri/simulation/matrix.rb +64 -0
- data/lib/y_petri/simulation/place_mapping.rb +62 -0
- data/lib/y_petri/simulation/place_representation.rb +74 -0
- data/lib/y_petri/simulation/places/access.rb +121 -0
- data/lib/y_petri/simulation/places/clamped.rb +8 -0
- data/lib/y_petri/simulation/places/free.rb +8 -0
- data/lib/y_petri/simulation/places/types.rb +25 -0
- data/lib/y_petri/simulation/places.rb +41 -0
- data/lib/y_petri/simulation/recorder.rb +54 -0
- data/lib/y_petri/simulation/timed/recorder.rb +53 -0
- data/lib/y_petri/simulation/timed.rb +161 -261
- data/lib/y_petri/simulation/timeless/recorder.rb +25 -0
- data/lib/y_petri/simulation/timeless.rb +35 -0
- data/lib/y_petri/simulation/transition_representation/A.rb +58 -0
- data/lib/y_petri/simulation/transition_representation/S.rb +45 -0
- data/lib/y_petri/simulation/transition_representation/T.rb +80 -0
- data/lib/y_petri/simulation/transition_representation/TS.rb +46 -0
- data/lib/y_petri/simulation/transition_representation/Ts.rb +32 -0
- data/lib/y_petri/simulation/transition_representation/a.rb +30 -0
- data/lib/y_petri/simulation/transition_representation/s.rb +29 -0
- data/lib/y_petri/simulation/transition_representation/t.rb +37 -0
- data/lib/y_petri/simulation/transition_representation/tS.rb +38 -0
- data/lib/y_petri/simulation/transition_representation/ts.rb +32 -0
- data/lib/y_petri/simulation/transition_representation/types.rb +62 -0
- data/lib/y_petri/simulation/transition_representation.rb +79 -0
- data/lib/y_petri/simulation/transitions/A.rb +40 -0
- data/lib/y_petri/simulation/transitions/S.rb +24 -0
- data/lib/y_petri/simulation/transitions/T.rb +34 -0
- data/lib/y_petri/simulation/transitions/TS.rb +57 -0
- data/lib/y_petri/simulation/transitions/Ts.rb +60 -0
- data/lib/y_petri/simulation/transitions/a.rb +8 -0
- data/lib/y_petri/simulation/transitions/access.rb +186 -0
- data/lib/y_petri/simulation/transitions/s.rb +9 -0
- data/lib/y_petri/simulation/transitions/t.rb +22 -0
- data/lib/y_petri/simulation/transitions/tS.rb +55 -0
- data/lib/y_petri/simulation/transitions/ts.rb +58 -0
- data/lib/y_petri/simulation/transitions/types.rb +98 -0
- data/lib/y_petri/simulation/transitions.rb +21 -0
- data/lib/y_petri/simulation.rb +176 -781
- data/lib/y_petri/transition/assignment.rb +7 -5
- data/lib/y_petri/transition/construction.rb +119 -187
- data/lib/y_petri/transition/init.rb +311 -0
- data/lib/y_petri/transition/ordinary_timeless.rb +8 -6
- data/lib/y_petri/transition/timed.rb +11 -18
- data/lib/y_petri/transition.rb +104 -132
- data/lib/y_petri/version.rb +1 -1
- data/lib/y_petri/world/dependency.rb +40 -0
- data/lib/y_petri/world/petri_net_related.rb +61 -0
- data/lib/y_petri/{workspace/simulation_related_methods.rb → world/simulation_related.rb} +42 -49
- data/lib/y_petri/world.rb +27 -0
- data/lib/y_petri.rb +47 -99
- data/test/{manipulator_test.rb → agent_test.rb} +19 -17
- data/{lib/y_petri → test/examples}/demonstrator.rb +0 -0
- data/{lib/y_petri → test/examples}/demonstrator_2.rb +1 -0
- data/{lib/y_petri → test/examples}/demonstrator_3.rb +0 -0
- data/{lib/y_petri → test/examples}/demonstrator_4.rb +0 -0
- data/test/examples/example_2.rb +16 -0
- data/test/{manual_examples.rb → examples/manual_examples.rb} +0 -0
- data/test/net_test.rb +126 -121
- data/test/place_test.rb +1 -1
- data/test/sim_test +565 -0
- data/test/simulation_test.rb +338 -264
- data/test/transition_test.rb +77 -174
- data/test/world_mock.rb +12 -0
- data/test/{workspace_test.rb → world_test.rb} +19 -20
- data/test/y_petri_test.rb +4 -5
- metadata +101 -26
- data/lib/y_petri/dependency_injection.rb +0 -45
- data/lib/y_petri/manipulator/petri_net_related_methods.rb +0 -74
- data/lib/y_petri/manipulator.rb +0 -20
- data/lib/y_petri/net/selections.rb +0 -209
- data/lib/y_petri/simulation/collections.rb +0 -460
- data/lib/y_petri/workspace/parametrized_subclassing.rb +0 -22
- data/lib/y_petri/workspace/petri_net_related_methods.rb +0 -88
- data/lib/y_petri/workspace.rb +0 -16
- data/test/timed_simulation_test.rb +0 -153
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b031424367891fe4ff8af4b6c61afb984f5d341
|
4
|
+
data.tar.gz: adb9f8df5d999a60beff42aa1f69fa9aed7f0a7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed934ecfc8a78e32d65b8174fee3eedab5ee969ae857b847698581ca3b33e002a4ead151e361caa2d14593efaf44d3d8b04b49f4c286f2a72173bd36c1314a25
|
7
|
+
data.tar.gz: c4fabc8dcf91e509e249dab7e0af4afb97ec2dc8d2b93b5bd18936e408915913e96ef45eb53756b34767257dff0d842194af6a992354e68f183facbad3b05f15
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Represents a pointer to a key of a specific hash associated with the pointer
|
2
|
-
# instance. Used to implement pointers of the
|
2
|
+
# instance. Used to implement pointers of the Agent class.
|
3
3
|
#
|
4
|
-
class YPetri::
|
4
|
+
class YPetri::Agent::HashKeyPointer
|
5
5
|
# Key at which the pointer points.
|
6
6
|
#
|
7
7
|
attr_reader :key
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Public command interface of YPetri.
|
4
|
+
#
|
5
|
+
module YPetri::Agent::PetriNetRelated
|
6
|
+
# Net selection class.
|
7
|
+
#
|
8
|
+
NetSelection = Class.new YPetri::Agent::Selection
|
9
|
+
|
10
|
+
# Net point
|
11
|
+
#
|
12
|
+
attr_reader :net_point
|
13
|
+
|
14
|
+
# Net selection.
|
15
|
+
#
|
16
|
+
attr_reader :net_selection
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
net_point_reset
|
20
|
+
@net_selection = NetSelection.new
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
# Elements and selections:
|
25
|
+
#
|
26
|
+
delegate :place, :transition, :element,
|
27
|
+
:nets, :places, :transitions,
|
28
|
+
to: :world
|
29
|
+
|
30
|
+
# Place name.
|
31
|
+
#
|
32
|
+
def pl( place_id )
|
33
|
+
place( place_id ).name
|
34
|
+
end
|
35
|
+
|
36
|
+
# Transition name.
|
37
|
+
#
|
38
|
+
def tr( transition_id )
|
39
|
+
transition( transition_id ).name
|
40
|
+
end
|
41
|
+
|
42
|
+
# Place names.
|
43
|
+
#
|
44
|
+
def pn
|
45
|
+
places.names
|
46
|
+
end
|
47
|
+
|
48
|
+
# Transition names.
|
49
|
+
#
|
50
|
+
def tn
|
51
|
+
transitions.names
|
52
|
+
end
|
53
|
+
|
54
|
+
# Net names.
|
55
|
+
#
|
56
|
+
def nn
|
57
|
+
nets.names
|
58
|
+
end
|
59
|
+
|
60
|
+
# Place constructor: Creates a new place in the current world.
|
61
|
+
#
|
62
|
+
def Place( *ordered_args, **named_args, &block )
|
63
|
+
fail ArgumentError, "If block is given, :guard named argument " +
|
64
|
+
"must not be given!" if named_args.has? :guard if block
|
65
|
+
named_args.update( guard: block ) if block # use block as a guard
|
66
|
+
named_args.may_have :default_marking, syn!: :m!
|
67
|
+
named_args.may_have :marking, syn!: :m
|
68
|
+
world.Place.new *ordered_args, **named_args
|
69
|
+
end
|
70
|
+
|
71
|
+
# Transition constructor: Creates a new transition in the current world.
|
72
|
+
#
|
73
|
+
def Transition( *ordered, **named, &block )
|
74
|
+
world.Transition.new *ordered, **named, &block
|
75
|
+
end
|
76
|
+
|
77
|
+
# Timed transition constructor: Creates a new timed transition in the current
|
78
|
+
# world. Rate closure has to be supplied as a block.
|
79
|
+
#
|
80
|
+
def T( *ordered, **named, &block )
|
81
|
+
world.Transition.new *ordered, **named.update( rate: block )
|
82
|
+
end
|
83
|
+
|
84
|
+
# Assignment transition constructor: Creates a new assignment transition in
|
85
|
+
# the current world. Assignment closure has to be supplied as a block.
|
86
|
+
#
|
87
|
+
def A( *ordered, **named, &block )
|
88
|
+
world.Transition.new *ordered,
|
89
|
+
**named.update( assignment: true, action: block )
|
90
|
+
end
|
91
|
+
|
92
|
+
# Net constructor: Creates a new Net instance in the current world.
|
93
|
+
#
|
94
|
+
def Net *ordered, **named, &block
|
95
|
+
world.Net.new *ordered, **named, &block
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns the net identified, or the net at point (if no argument given).
|
99
|
+
#
|
100
|
+
def net id=nil
|
101
|
+
id.nil? ? @net_point : world.net( id )
|
102
|
+
end
|
103
|
+
|
104
|
+
# Sets the net point to a given net, or to world.Net::Top if none given.
|
105
|
+
#
|
106
|
+
def net_point_reset id=world.Net::Top
|
107
|
+
@net_point = world.net( id )
|
108
|
+
end
|
109
|
+
|
110
|
+
# Sets net point to a given net.
|
111
|
+
#
|
112
|
+
def net_point= id
|
113
|
+
net_point_reset id
|
114
|
+
end
|
115
|
+
end # module YPetri::Agent::PetriNetRelated
|
@@ -1,32 +1,34 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
#
|
4
|
-
# of simulations...)
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Agent instance methods related to simulation (initial marking collections,
|
4
|
+
# clamp collections, initial marking collections, management of simulations...)
|
5
5
|
#
|
6
|
-
module YPetri::
|
6
|
+
module YPetri::Agent::SimulationRelated
|
7
7
|
require_relative 'hash_key_pointer'
|
8
8
|
require_relative 'selection'
|
9
9
|
|
10
10
|
# Simulation selection class.
|
11
11
|
#
|
12
|
-
SimulationSelection =
|
12
|
+
SimulationSelection = YPetri::Agent::Selection.parametrize agent: self
|
13
13
|
|
14
14
|
# Simulation settings collection selection class.
|
15
15
|
#
|
16
|
-
SscSelection =
|
16
|
+
SscSelection = YPetri::Agent::Selection.parametrize agent: self
|
17
17
|
|
18
18
|
# Clamp collection selection class.
|
19
19
|
#
|
20
|
-
CcSelection =
|
20
|
+
CcSelection = YPetri::Agent::Selection.parametrize agent: self
|
21
21
|
|
22
22
|
# Initial marking collection selection class.
|
23
23
|
#
|
24
|
-
ImcSelection =
|
24
|
+
ImcSelection = YPetri::Agent::Selection.parametrize agent: self
|
25
25
|
|
26
|
-
class SimulationPoint < YPetri::
|
26
|
+
class SimulationPoint < YPetri::Agent::HashKeyPointer
|
27
27
|
# Reset to the first simulation, or nil if that is absent.
|
28
28
|
#
|
29
|
-
def reset
|
29
|
+
def reset
|
30
|
+
@key = @hash.empty? ? nil : set( @hash.first[0] )
|
31
|
+
end
|
30
32
|
|
31
33
|
# A simulation is identified either by its name (if named), or by its
|
32
34
|
# parameters and settings (:net, :cc, :imc, :ssc).
|
@@ -47,19 +49,24 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
47
49
|
|
48
50
|
# Pointer to a collection of simulation settings.
|
49
51
|
#
|
50
|
-
SscPoint =
|
52
|
+
SscPoint = YPetri::Agent::HashKeyPointer.parametrize agent: self
|
51
53
|
|
52
54
|
# Pointer to a clamp collection.
|
53
55
|
#
|
54
|
-
CcPoint =
|
56
|
+
CcPoint = YPetri::Agent::HashKeyPointer.parametrize agent: self
|
55
57
|
|
56
58
|
# Pointer to a collection of initial markings.
|
57
59
|
#
|
58
|
-
ImcPoint =
|
60
|
+
ImcPoint = YPetri::Agent::HashKeyPointer.parametrize agent: self
|
59
61
|
|
60
|
-
attr_reader :simulation_point,
|
61
|
-
:
|
62
|
-
:
|
62
|
+
attr_reader :simulation_point,
|
63
|
+
:ssc_point,
|
64
|
+
:cc_point,
|
65
|
+
:imc_point,
|
66
|
+
:simulation_selection,
|
67
|
+
:ssc_selection,
|
68
|
+
:cc_selection,
|
69
|
+
:imc_selection
|
63
70
|
|
64
71
|
def initialize
|
65
72
|
# set up this manipulator's pointers
|
@@ -83,20 +90,20 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
83
90
|
super
|
84
91
|
end
|
85
92
|
|
86
|
-
# Simulation-related methods delegated to the
|
93
|
+
# Simulation-related methods delegated to the world.
|
87
94
|
delegate :simulations,
|
88
95
|
:clamp_collections,
|
89
96
|
:initial_marking_collections,
|
90
97
|
:simulation_settings_collections,
|
91
|
-
:clamp_collection_names, :
|
92
|
-
:initial_marking_collection_names, :
|
93
|
-
:simulation_settings_collection_names, :
|
94
|
-
:set_clamp_collection, :
|
95
|
-
:set_initial_marking_collection, :
|
98
|
+
:clamp_collection_names, :ncc,
|
99
|
+
:initial_marking_collection_names, :nimc,
|
100
|
+
:simulation_settings_collection_names, :nssc,
|
101
|
+
:set_clamp_collection, :ncc,
|
102
|
+
:set_initial_marking_collection, :nimc,
|
96
103
|
:set_simulation_settings_collection, :set_ssc,
|
97
|
-
:
|
104
|
+
:new_simulation,
|
98
105
|
:clamp_cc, :initial_marking_cc, :simulation_settings_cc,
|
99
|
-
to: :
|
106
|
+
to: :world
|
100
107
|
|
101
108
|
# Returns the simulation identified by the argument, or one at simulation
|
102
109
|
# point, if no argument given. The simulation is identified in the same way
|
@@ -107,10 +114,6 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
107
114
|
SimulationPoint.new( hash: simulations, hash_value_is: "simulation" ).get
|
108
115
|
end
|
109
116
|
|
110
|
-
# # TEMPORARY KLUGE - FIXME
|
111
|
-
# #
|
112
|
-
# def simulation; @workspace.simulations.values[-1] end
|
113
|
-
|
114
117
|
# Returns identified clamp collection, or (if no argument given) one
|
115
118
|
# corresponding to cc_point.
|
116
119
|
#
|
@@ -143,7 +146,7 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
143
146
|
|
144
147
|
def clamp clamp_hash
|
145
148
|
clamp_hash.each_pair do |place, clamp|
|
146
|
-
clamp_collection.merge!
|
149
|
+
clamp_collection.merge! world.place( place ) => clamp
|
147
150
|
end
|
148
151
|
end
|
149
152
|
|
@@ -151,7 +154,7 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
151
154
|
# field:
|
152
155
|
# * No arguments: returns current imc
|
153
156
|
# * Exactly one ordered argument: it is assumed to identify a place whose
|
154
|
-
# im in
|
157
|
+
# im in the current imc will be returned.
|
155
158
|
# * A hash: Assumed to be { place_id => im }, current imc is updated with it.
|
156
159
|
# * One ordered argument, and a hash: The imc identified by the ordered
|
157
160
|
# ordered arg is updated with the hash.
|
@@ -222,8 +225,8 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
222
225
|
# Create a new timed simulation and make it available in the simulations
|
223
226
|
# table.
|
224
227
|
#
|
225
|
-
def
|
226
|
-
instance =
|
228
|
+
def new_simulation *args, &block
|
229
|
+
instance = world.new_simulation( *args, &block )
|
227
230
|
# Set the point to it
|
228
231
|
simulation_point.set( simulations.rassoc( instance )[0] )
|
229
232
|
return instance
|
@@ -232,43 +235,37 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
232
235
|
# Create a new timed simulation and run it.
|
233
236
|
#
|
234
237
|
def run!
|
235
|
-
|
238
|
+
new_simulation.run!
|
236
239
|
end
|
237
240
|
|
238
241
|
# Write the recorded samples in a file (csv).
|
239
242
|
#
|
240
|
-
def print_recording( filename
|
243
|
+
def print_recording( filename=nil )
|
241
244
|
if filename.nil? then
|
242
|
-
puts simulation.
|
245
|
+
puts simulation.recording.to_csv
|
243
246
|
else
|
244
247
|
File.open( filename, "w" ) do |f|
|
245
|
-
f << simulation.
|
248
|
+
f << simulation.recording.to_csv
|
246
249
|
end
|
247
250
|
end
|
248
251
|
end
|
249
252
|
|
250
253
|
# Plot the recorded samples.
|
251
254
|
#
|
252
|
-
def plot
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
case plot_what
|
259
|
-
when :state then plot_recording oo
|
260
|
-
when :flux then plot_flux oo
|
261
|
-
when :all then plot_all oo
|
262
|
-
else plot_selected *args end
|
263
|
-
else raise "Too many ordered arguments!" end
|
264
|
-
end
|
255
|
+
def plot **features
|
256
|
+
# --> state feature ids
|
257
|
+
# --> gradient feature ids
|
258
|
+
# --> delta feature ids
|
259
|
+
# --> flux feature ids
|
260
|
+
# --> firing feature ids
|
265
261
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
262
|
+
# take these features together
|
263
|
+
|
264
|
+
# construct the labels and the time series for each
|
265
|
+
|
266
|
+
# plot them
|
267
|
+
|
268
|
+
return nil unless sim = world.simulations.values[-1] # sim@point
|
272
269
|
# Decide abnout the features
|
273
270
|
features = sim.places.dup.map { |p|
|
274
271
|
collection.include?( p ) ? p : nil
|
@@ -285,82 +282,68 @@ module YPetri::Manipulator::SimulationRelatedMethods
|
|
285
282
|
gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
|
286
283
|
title: "Selected features plot", ylabel: "Marking" )
|
287
284
|
end
|
288
|
-
|
289
285
|
|
290
286
|
# Plot the recorded samples (system state history).
|
291
287
|
#
|
292
|
-
def plot_state(
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
features = excluded.each_with_object sim.places.dup do |x, α|
|
298
|
-
i = α.index x
|
299
|
-
α[i] = nil if i
|
300
|
-
end
|
301
|
-
# Get recording
|
302
|
-
rec = sim.recording
|
303
|
-
# Select a time series for each feature.
|
304
|
-
time_series = features.map.with_index do |feature, i|
|
305
|
-
feature and rec.map { |key, val| [ key, val[i] ] }.transpose
|
306
|
-
end
|
307
|
-
# Time axis
|
308
|
-
ᴛ = sim.target_time
|
309
|
-
# Gnuplot call
|
310
|
-
gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
|
311
|
-
title: "State plot", ylabel: "Marking" )
|
288
|
+
def plot_state( place_ids=nil, except: [] )
|
289
|
+
sim = simulation or return nil
|
290
|
+
feat = sim.pp( place_ids || sim.pp ) - sim.pp( Array except )
|
291
|
+
gnuplot sim.record.marking( feat ), time: sim.target_time,
|
292
|
+
title: "State plot", ylabel: "Marking"
|
312
293
|
end
|
294
|
+
alias plot_marking plot_state
|
313
295
|
|
314
296
|
# Plot the recorded flux (computed flux history at the sampling points).
|
315
297
|
#
|
316
|
-
def plot_flux(
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
if i then α[i] = nil end
|
298
|
+
def plot_flux( transition_ids=nil, **options )
|
299
|
+
sim = world.simulations.values[-1] or return nil # sim@point
|
300
|
+
tt = sim.TS_transitions( transition_ids ).sources
|
301
|
+
excluded = sim.transitions( Array options[:except] ).sources
|
302
|
+
tt -= excluded
|
303
|
+
flux = sim.recording.modify do |time, record|
|
304
|
+
[ time,
|
305
|
+
sim.at( time: time, marking: record ).TS_transitions( tt ).flux_vector ]
|
325
306
|
end
|
326
|
-
# Get recording.
|
327
|
-
rec = sim.recording
|
328
|
-
# Get flux recording.
|
329
|
-
flux = rec.modify { |ᴛ, ᴍ| [ ᴛ, sim.at( t: ᴛ, m: ᴍ ).flux_for( *all ) ] }
|
330
307
|
# Select a time series for each feature.
|
331
|
-
time_series =
|
332
|
-
|
308
|
+
time_series = tt.map.with_index do |tr, i|
|
309
|
+
tr and flux.map { |time, flux| [ time, flux[i] ] }.transpose
|
333
310
|
end
|
334
311
|
# Time axis
|
335
|
-
|
312
|
+
time = sim.target_time
|
336
313
|
# Gnuplot call
|
337
|
-
gnuplot(
|
314
|
+
gnuplot( time, tt.compact.names, time_series.compact,
|
338
315
|
title: "Flux plot", ylabel: "Flux [µMⁿ.s⁻¹]" )
|
339
316
|
end
|
340
317
|
|
341
318
|
private
|
342
319
|
|
343
|
-
# Gnuplots
|
320
|
+
# Gnuplots a recording. Target time or time range can be supplied as :time
|
321
|
+
# named argument.
|
344
322
|
#
|
345
|
-
def gnuplot(
|
346
|
-
|
347
|
-
|
348
|
-
|
323
|
+
def gnuplot( dataset, time: nil, **nn )
|
324
|
+
event_vector = dataset.events
|
325
|
+
data_vectors = dataset.values.transpose
|
326
|
+
x_range = if time.is_a? Range then
|
327
|
+
"[#{time.begin}:#{time.end}]"
|
328
|
+
else
|
329
|
+
"[-0:#{SY::Time.magnitude( time ).amount rescue time}]"
|
330
|
+
end
|
331
|
+
labels = recording.features.labels
|
349
332
|
|
350
333
|
Gnuplot.open do |gp|
|
351
334
|
Gnuplot::Plot.new( gp ) do |plot|
|
352
|
-
plot.xrange
|
353
|
-
plot.title
|
354
|
-
plot.ylabel
|
355
|
-
plot.xlabel
|
356
|
-
|
357
|
-
labels.zip(
|
358
|
-
plot.data << Gnuplot::DataSet.new(
|
359
|
-
|
360
|
-
|
361
|
-
|
335
|
+
plot.xrange x_range
|
336
|
+
plot.title nn[:title] || "Simulation plot"
|
337
|
+
plot.ylabel nn[:ylabel] || "Values"
|
338
|
+
plot.xlabel nn[:xlabel] || "Time [s]"
|
339
|
+
|
340
|
+
labels.zip( data_vectors ).each { |label, data_vector|
|
341
|
+
plot.data << Gnuplot::DataSet.new( [event_vector, data_vector] ) { |ds|
|
342
|
+
ds.with = "linespoints"
|
343
|
+
ds.title = lbl
|
344
|
+
}
|
362
345
|
}
|
363
346
|
end
|
364
347
|
end
|
365
348
|
end
|
366
|
-
end # module YPetri::
|
349
|
+
end # module YPetri::Agent::SimulationRelated
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
# Public command interface of YPetri.
|
4
|
+
#
|
5
|
+
module YPetri
|
6
|
+
class Agent
|
7
|
+
attr_reader :world
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@world = YPetri::World.new
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
require_relative 'agent/selection'
|
15
|
+
require_relative 'agent/hash_key_pointer'
|
16
|
+
require_relative 'agent/petri_net_related'
|
17
|
+
require_relative 'agent/simulation_related'
|
18
|
+
|
19
|
+
include self::PetriNetRelated
|
20
|
+
include self::SimulationRelated
|
21
|
+
end # class Agent
|
22
|
+
end # module YPetri
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Euler method.
|
4
|
+
#
|
5
|
+
class YPetri::Core::Timed
|
6
|
+
module Euler
|
7
|
+
# Name of this method.
|
8
|
+
#
|
9
|
+
def simulation_method
|
10
|
+
:euler
|
11
|
+
end
|
12
|
+
|
13
|
+
# Computes Δ for the period of Δt.
|
14
|
+
#
|
15
|
+
def delta Δt
|
16
|
+
gradient * Δt
|
17
|
+
end
|
18
|
+
alias Δ delta
|
19
|
+
end # Euler
|
20
|
+
end # YPetri::Core::Timed
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Euler method with timeless transitions firing after each step.
|
4
|
+
#
|
5
|
+
class YPetri::Core::Timed
|
6
|
+
module PseudoEuler
|
7
|
+
include Euler
|
8
|
+
|
9
|
+
# Name of this method.
|
10
|
+
#
|
11
|
+
def simulation_method
|
12
|
+
:pseudo_euler
|
13
|
+
end
|
14
|
+
|
15
|
+
# Computes Δ for the period of Δt.
|
16
|
+
#
|
17
|
+
def delta Δt
|
18
|
+
super + delta_timeless
|
19
|
+
end
|
20
|
+
alias Δ delta
|
21
|
+
|
22
|
+
# Makes a single step by Δt.
|
23
|
+
#
|
24
|
+
def step! Δt=simulation.step
|
25
|
+
increment_marking_vector Δ( Δt )
|
26
|
+
assignment_transitions_all_fire!
|
27
|
+
simulation.increment_time! Δt
|
28
|
+
alert
|
29
|
+
end
|
30
|
+
end # PseudoEuler
|
31
|
+
end # YPetri::Core::Timed
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Euler method with timeless transitions firing every time tick.
|
4
|
+
#
|
5
|
+
class YPetri::Core::Timed
|
6
|
+
module QuasiEuler
|
7
|
+
include Euler
|
8
|
+
|
9
|
+
# Name of this method.
|
10
|
+
#
|
11
|
+
def simulation_method
|
12
|
+
:quasi_euler
|
13
|
+
end
|
14
|
+
|
15
|
+
# Makes a single step by Δt.
|
16
|
+
#
|
17
|
+
def step! Δt=simulation.step_size
|
18
|
+
fail NotImplementedError
|
19
|
+
# Now one would have to compare whichever comes first, time tick or the
|
20
|
+
# end of Δt, and then again and again, until Δt is fired...
|
21
|
+
end
|
22
|
+
end # QuasiEuler
|
23
|
+
end # YPetri::Core::Timed
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Timed simulation core.
|
4
|
+
#
|
5
|
+
class YPetri::Core
|
6
|
+
class Timed < YPetri::Core
|
7
|
+
require_relative 'timed/euler.rb'
|
8
|
+
require_relative 'timed/pseudo_euler.rb' # timeless fire after each step
|
9
|
+
require_relative 'timed/quasi_euler.rb' # timeless fire each time tick
|
10
|
+
|
11
|
+
# Makes a single step by Δt.
|
12
|
+
#
|
13
|
+
def step! Δt=simulation.step
|
14
|
+
increment_marking_vector Δ( Δt )
|
15
|
+
increment_time! Δt
|
16
|
+
note_state_change
|
17
|
+
end
|
18
|
+
|
19
|
+
# Gradient for free places.
|
20
|
+
#
|
21
|
+
def gradient
|
22
|
+
gradient_Ts + gradient_TS
|
23
|
+
end
|
24
|
+
alias ∇ gradient
|
25
|
+
|
26
|
+
# Gradient contribution by Ts transitions.
|
27
|
+
#
|
28
|
+
def gradient_Ts
|
29
|
+
simulation.Ts_gradient_closure.call
|
30
|
+
end
|
31
|
+
|
32
|
+
# Gradient contribution by TS transitions.
|
33
|
+
#
|
34
|
+
def gradient_TS
|
35
|
+
( simulation.TS_stoichiometry_matrix * flux_vector_TS )
|
36
|
+
end
|
37
|
+
|
38
|
+
# Flux vector. The caller asserts that all the timed transitions are
|
39
|
+
# stoichiometric, or error.
|
40
|
+
#
|
41
|
+
def flux_vector
|
42
|
+
msg = "#flux_vector method only applies to the timed simulations with " +
|
43
|
+
"no Ts transitions. Try #flux_vector_TS instead!"
|
44
|
+
fail msg unless Ts_transitions().empty?
|
45
|
+
simulation.TS_rate_closure.call
|
46
|
+
end
|
47
|
+
|
48
|
+
# Flux vector of TS transitions.
|
49
|
+
#
|
50
|
+
def flux_vector_TS
|
51
|
+
simulation.TS_rate_closure.call
|
52
|
+
end
|
53
|
+
end # class Timed
|
54
|
+
end # class YPetri::Core
|
55
|
+
|
56
|
+
# In general, it is not required that all net elements are simulated with the
|
57
|
+
# same method. Practically, ODE systems have many good simulation methods
|
58
|
+
# available.
|
59
|
+
#
|
60
|
+
# (1) ᴍ(t) = ϝ f(ᴍ, t).dt, where f(ᴍ, t) is a known function.
|
61
|
+
#
|
62
|
+
# Many of these methods depend on the Jacobian, but that may not be available
|
63
|
+
# for some places. Therefore, the places, whose marking defines the system
|
64
|
+
# state, are divided into two categories: "A" (accelerated), for which as
|
65
|
+
# common Jacobian can be found, and "E" places, where "E" can stand either for
|
66
|
+
# "External" or "Euler".
|
67
|
+
#
|
68
|
+
# If we apply the definition of "causal orientation" on A and E places, then it
|
69
|
+
# can be said, that only the transitions causally oriented towards "A" places
|
70
|
+
# are allowed for compliance with the equation (1).
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Implicit Euler for timeless nets. Simply, timeless transitions
|
4
|
+
# fire simultaneously, after which A transitions (if any) fire.
|
5
|
+
#
|
6
|
+
class YPetri::Core::Timeless
|
7
|
+
module PseudoEuler
|
8
|
+
# Name of this method.
|
9
|
+
#
|
10
|
+
def simulation_method
|
11
|
+
:pseudo_euler
|
12
|
+
end
|
13
|
+
|
14
|
+
def step!
|
15
|
+
increment_marking_vector Δ
|
16
|
+
assignment_transitions_all_fire!
|
17
|
+
alert
|
18
|
+
end
|
19
|
+
end # module PseudoEuler
|
20
|
+
end # class YPetri::Core::Timeless
|