y_petri 2.0.15 → 2.1.3
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/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
|