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/lib/y_petri/simulation.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require_relative 'simulation/matrix'
|
4
4
|
require_relative 'simulation/dependency'
|
5
|
-
require_relative 'simulation/
|
6
|
-
require_relative 'simulation/
|
7
|
-
require_relative 'simulation/
|
5
|
+
require_relative 'simulation/node_representation'
|
6
|
+
require_relative 'simulation/nodes'
|
7
|
+
require_relative 'simulation/nodes/access'
|
8
8
|
require_relative 'simulation/place_representation'
|
9
9
|
require_relative 'simulation/places'
|
10
10
|
require_relative 'simulation/places/access'
|
@@ -22,22 +22,22 @@ require_relative 'simulation/recorder'
|
|
22
22
|
require_relative 'simulation/timeless'
|
23
23
|
require_relative 'simulation/timed'
|
24
24
|
|
25
|
-
# Represents a Petri net simulation
|
26
|
-
# settings, initial values, marking clamps
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# belong</b> to the model, although for convenience, places may carry default
|
30
|
-
# initial marking, guards, and clamps for use in the token game. Simulation
|
31
|
-
# instance can also use these if none other are specified.
|
25
|
+
# Represents a Petri net simulation. Its concerns include the simulation method,
|
26
|
+
# simulation settings, initial values, marking clamps used during the simulation,
|
27
|
+
# guards etc. Its concerns do not include the Petri net domain model as such
|
28
|
+
# (places, transitions, arcs, transition functions...)
|
32
29
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
30
|
+
# In a simulation, some places are designated as free (ie. their marking is free
|
31
|
+
# to be changed by firing of the net's transitions), while others are clamped
|
32
|
+
# (their marking is clamped by the simulation rather than changed by the
|
33
|
+
# transitions). For free places, initial marking has to be specified. For
|
34
|
+
# clamped places, marking clamps have to be specified. (For convenience, places
|
35
|
+
# may carry their own initial marking.)
|
36
36
|
#
|
37
37
|
class YPetri::Simulation
|
38
38
|
★ Places::Access # ★ means include
|
39
39
|
★ Transitions::Access
|
40
|
-
★
|
40
|
+
★ Nodes::Access
|
41
41
|
★ InitialMarking::Access
|
42
42
|
★ MarkingClamps::Access
|
43
43
|
★ MarkingVector::Access
|
@@ -52,7 +52,7 @@ class YPetri::Simulation
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
# Parametrized subclasses
|
55
|
+
# Parametrized subclasses.
|
56
56
|
attr_reader :core,
|
57
57
|
:recorder,
|
58
58
|
:guarded,
|
@@ -64,7 +64,7 @@ class YPetri::Simulation
|
|
64
64
|
:Ts_gradient_closure,
|
65
65
|
:tS_firing_closure,
|
66
66
|
:TS_rate_closure,
|
67
|
-
:
|
67
|
+
:A_direct_assignment_closure,
|
68
68
|
:increment_marking_vector_closure
|
69
69
|
|
70
70
|
alias guarded? guarded
|
@@ -72,12 +72,12 @@ class YPetri::Simulation
|
|
72
72
|
delegate :net, to: "self.class"
|
73
73
|
|
74
74
|
delegate :simulation_method,
|
75
|
-
:guarded?,
|
76
75
|
:step!,
|
77
76
|
:firing_vector_tS,
|
78
77
|
to: :core
|
79
78
|
|
80
79
|
delegate :recording,
|
80
|
+
:back!,
|
81
81
|
to: :recorder
|
82
82
|
|
83
83
|
alias r recording
|
@@ -99,7 +99,7 @@ class YPetri::Simulation
|
|
99
99
|
|
100
100
|
# Firing of the indicated tS transitions (as hash with transition names as
|
101
101
|
# keys).
|
102
|
-
#
|
102
|
+
#
|
103
103
|
def t_firing ids=nil
|
104
104
|
tS_transitions( ids ).names( true ) >> firing( ids )
|
105
105
|
end
|
@@ -113,69 +113,63 @@ class YPetri::Simulation
|
|
113
113
|
t_firing( ids ).pretty_print_numeric_values( gap: gap, precision: precision )
|
114
114
|
end
|
115
115
|
|
116
|
-
# The basic simulation parameter is
|
117
|
-
#
|
118
|
-
# required
|
116
|
+
# The basic simulation parameter is +:net+ – a collection of places and
|
117
|
+
# transitions (a <tt>YPetri::Net</tt> instance) that is simulated. Other
|
118
|
+
# required arguments are +:marking_clamps+ and +:initial_marking+
|
119
119
|
# (or +:marking -- if no +:initial_marking+ is supplied, +:marking+ will be
|
120
|
-
# used in its stead).
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
# set. Setting +:use_default_marking+ to _false_ will cause an error unless
|
126
|
-
# +:initial_marking+ and +:place_clamps+ are supplied explicitly.
|
120
|
+
# used in its stead). Even when the caller did not provide all the
|
121
|
+
# +:initial_marking+, there is an option of extracting them from the place
|
122
|
+
# instances themselves. This option, controlled by the named argument
|
123
|
+
# +use_default_marking+, is normally set to _true_, to turn it off, change
|
124
|
+
# it to _false_.
|
127
125
|
#
|
128
|
-
# Simulation method is
|
129
|
-
#
|
130
|
-
#
|
131
|
-
# (alias +:time_range+), +:step
|
132
|
-
#
|
133
|
-
# arguments
|
126
|
+
# Simulation method is set by +:method+ named argument, guarding is controlled
|
127
|
+
# by +:guarded+ named argument (_true_/_false_). Simulations of timed nets are
|
128
|
+
# also timed. For a timed simulation, the constructor permits named arguments
|
129
|
+
# +:time+ (alias +:time_range+), +:step+ (simulation step size), and
|
130
|
+
# +:sampling+ (sampling period), and requires that at least one of these named
|
131
|
+
# arguments be supplied.
|
134
132
|
#
|
135
|
-
def initialize
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
else true end
|
143
|
-
# Time-independent simulation settings received, constructing param. classes
|
144
|
-
param_class!( { Place: PlaceRepresentation,
|
133
|
+
def initialize use_default_marking: true,
|
134
|
+
guarded: false,
|
135
|
+
marking_clamps: {},
|
136
|
+
initial_marking: {},
|
137
|
+
marking: nil,
|
138
|
+
**settings
|
139
|
+
param_class!( { Place: PlaceRepresentation, # parametrized subclasses
|
145
140
|
Places: Places,
|
146
141
|
Transition: TransitionRepresentation,
|
147
142
|
Transitions: Transitions,
|
143
|
+
Nodes: Nodes,
|
148
144
|
PlaceMapping: PlaceMapping,
|
149
145
|
InitialMarking: InitialMarking,
|
150
146
|
MarkingClamps: MarkingClamps,
|
151
147
|
MarkingVector: MarkingVector },
|
152
148
|
with: { simulation: self } )
|
153
|
-
|
154
|
-
|
155
|
-
Transition().namespace!
|
156
|
-
# Set up the places collection.
|
149
|
+
[ Place(), Transition() ].each &:namespace! # each serves as its namespace
|
150
|
+
@guarded = guarded # TODO: Not operable as of now.
|
157
151
|
@places = Places().load( net.places )
|
158
|
-
|
159
|
-
@
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
# Correspondence matrix free --> all
|
152
|
+
@marking_clamps = MarkingClamps().load( marking_clamps )
|
153
|
+
@initial_marking = if marking then
|
154
|
+
m = PlaceMapping().load( marking )
|
155
|
+
im = PlaceMapping().load( initial_marking )
|
156
|
+
InitialMarking().load( m.merge im )
|
157
|
+
else
|
158
|
+
InitialMarking().load( initial_marking )
|
159
|
+
end
|
160
|
+
# Fill in the missing initial marking from the places' default marking.
|
161
|
+
@places.send( :complete_initial_marking,
|
162
|
+
use_default_marking: use_default_marking )
|
163
|
+
# Correspondence matrix free places --> all places
|
170
164
|
@f2a = free_places.correspondence_matrix( places )
|
171
|
-
# Correspondence matrix clamped --> all
|
165
|
+
# Correspondence matrix clamped places --> all places
|
172
166
|
@c2a = clamped_places.correspondence_matrix( places )
|
173
167
|
# Conditionally extend self depending on net's timedness.
|
174
|
-
|
175
|
-
|
168
|
+
time_mentioned = settings[:time] || settings[:step] || settings[:sampling]
|
169
|
+
if time_mentioned then extend Timed else extend Timeless end
|
176
170
|
# Initialize the marking vector.
|
177
171
|
@m_vector = MarkingVector().zero
|
178
|
-
# Set up the transitions
|
172
|
+
# Set up the collection of transitions.
|
179
173
|
@transitions = Transitions().load( net.transitions )
|
180
174
|
# Set up stoichiometry matrices relative to free places.
|
181
175
|
@tS_stoichiometry_matrix = transitions.tS.stoichiometry_matrix
|
@@ -183,46 +177,48 @@ class YPetri::Simulation
|
|
183
177
|
# Set up stoichiometry matrices relative to all places.
|
184
178
|
@tS_SM = transitions.tS.SM
|
185
179
|
@TS_SM = transitions.TS.SM
|
186
|
-
# Call timedness-dependent
|
180
|
+
# Call timedness-dependent #init subroutine.
|
187
181
|
init **settings
|
188
|
-
# Make
|
182
|
+
# Make time-independent closures.
|
189
183
|
@ts_delta_closure = transitions.ts.delta_closure
|
190
184
|
@tS_firing_closure = transitions.tS.firing_closure
|
191
|
-
@
|
185
|
+
@A_direct_assignment_closure = transitions.A.direct_assignment_closure
|
192
186
|
@increment_marking_vector_closure = m_vector.increment_closure
|
193
|
-
# Make timed closures.
|
187
|
+
# Make timed-only closures.
|
194
188
|
if timed? then
|
195
189
|
@Ts_gradient_closure = transitions.Ts.gradient_closure
|
196
190
|
@TS_rate_closure = transitions.TS.rate_closure
|
197
191
|
end
|
198
192
|
# Reset.
|
199
|
-
if
|
193
|
+
if marking then reset! marking: marking else reset! end
|
200
194
|
end
|
201
195
|
|
202
196
|
# Simulation settings.
|
203
197
|
#
|
204
198
|
def settings all=false
|
205
199
|
return { method: simulation_method, guarded: guarded? } unless all == true
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
200
|
+
{ net: net,
|
201
|
+
marking_clamps: marking_clamps.keys_to_source_places,
|
202
|
+
initial_marking: initial_markings.keys_to_source_places
|
203
|
+
}.update( settings )
|
210
204
|
end
|
211
205
|
|
212
206
|
# Returns a new simulation instance. Unless modified by arguments, the state
|
213
207
|
# of the new instance is the same as the creator's. Arguments can partially or
|
214
208
|
# wholly modify the attributes of the duplicate.
|
215
209
|
#
|
216
|
-
def dup( marking: marking, recording: recording, **
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
210
|
+
def dup( marking: marking, recording: recording, **named_args )
|
211
|
+
named_args.reverse_merge! settings( true )
|
212
|
+
self.class.new( named_args ).tap do |duplicate|
|
213
|
+
duplicate.recorder.reset! recording: recording
|
214
|
+
duplicate.m_vector.reset! case marking
|
215
|
+
when Hash then
|
216
|
+
m_vector.to_hash_with_source_places
|
217
|
+
.update( PlaceMapping().load( marking )
|
218
|
+
.to_marking_vector
|
219
|
+
.to_hash_with_source_places )
|
220
|
+
when Matrix, Array then marking
|
221
|
+
else marking.each.to_a end
|
226
222
|
end
|
227
223
|
end
|
228
224
|
|
@@ -240,12 +236,10 @@ class YPetri::Simulation
|
|
240
236
|
|
241
237
|
# Resets the simulation.
|
242
238
|
#
|
243
|
-
def reset! **
|
244
|
-
m = nn[:marking]
|
239
|
+
def reset! marking: nil, **named_args
|
245
240
|
tap do
|
246
|
-
|
247
|
-
recorder.reset!
|
248
|
-
recorder.alert
|
241
|
+
marking ? m_vector.reset!( marking ) : m_vector.reset!
|
242
|
+
recorder.reset!.alert!
|
249
243
|
end
|
250
244
|
end
|
251
245
|
|
@@ -258,7 +252,7 @@ class YPetri::Simulation
|
|
258
252
|
|
259
253
|
# Extract a prescribed set of features.
|
260
254
|
#
|
261
|
-
def get_features
|
262
|
-
net.State.
|
255
|
+
def get_features *args
|
256
|
+
net.State.Features( *args ).extract_from( self )
|
263
257
|
end
|
264
258
|
end # class YPetri::Simulation
|
data/lib/y_petri/transition/A.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
3
|
# Mixin for the transitions with assignment action.
|
4
4
|
#
|
@@ -24,7 +24,7 @@ module YPetri::Transition::Type_A
|
|
24
24
|
msg = "Wrong output arity of the action closure of #{self}"
|
25
25
|
fail TypeError, msg if act.size != codomain.size
|
26
26
|
codomain.each_with_index { |p, i|
|
27
|
-
note "assigning action
|
27
|
+
note "assigning action node no. #{i} to #{p}"
|
28
28
|
p.marking = note "marking to assign", is: act.fetch( i )
|
29
29
|
}
|
30
30
|
end
|
@@ -36,4 +36,10 @@ module YPetri::Transition::Type_A
|
|
36
36
|
def enabled?
|
37
37
|
true
|
38
38
|
end
|
39
|
+
|
40
|
+
# Transition's assignment action under current simulation.
|
41
|
+
#
|
42
|
+
def a simulation=world.simulation
|
43
|
+
simulation.net.State.Feature.Assignment( self ) % simulation
|
44
|
+
end
|
39
45
|
end # class YPetri::Transition::Type_A
|
data/lib/y_petri/transition/T.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
3
|
# Mixin for timed Petri net transitions.
|
4
4
|
#
|
@@ -30,7 +30,7 @@ module YPetri::Transition::Type_T
|
|
30
30
|
msg = "Wrong output arity of the action closure of #{self}!"
|
31
31
|
fail TypeError, msg if act.size != codomain.size
|
32
32
|
codomain.each_with_index do |p, i|
|
33
|
-
note "adding action
|
33
|
+
note "adding action node no. #{i} to #{p}"
|
34
34
|
p.add note( "marking change", is: act.fetch( i ) )
|
35
35
|
end
|
36
36
|
end
|
@@ -47,4 +47,27 @@ module YPetri::Transition::Type_T
|
|
47
47
|
rescue YPetri::GuardError; false end
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
# Transition's firing under current simulation.
|
52
|
+
#
|
53
|
+
def fir simulation=world.simulation, **nn
|
54
|
+
nn.must_have :delta_time, syn!: :Δt
|
55
|
+
Δt = nn.delete( :delta_time ) || simulation.step
|
56
|
+
simulation.net.State.Feature.Firing( self ) % [ simulation, Δt: Δt ]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Transition's flux under current simulation.
|
60
|
+
#
|
61
|
+
def f simulation=world.simulation
|
62
|
+
simulation.net.State.Feature.Flux( self ) % simulation
|
63
|
+
end
|
64
|
+
|
65
|
+
# Prints the transition's action under current simulation.
|
66
|
+
#
|
67
|
+
def pa simulation=world.simulation, **nn
|
68
|
+
nn.must_have :delta_time, syn!: :Δt
|
69
|
+
Δt = nn.delete( :delta_time ) || simulation.step
|
70
|
+
ff = simulation.net.State.Features.Delta( codomain, transitions: self )
|
71
|
+
( ff >> ff % simulation ).pretty_print_numeric_values( **nn )
|
72
|
+
end
|
50
73
|
end # class YPetri::Transition::Type_T
|
@@ -15,11 +15,27 @@ module YPetri::Transition::Arcs
|
|
15
15
|
|
16
16
|
# Union of action arcs and test arcs.
|
17
17
|
#
|
18
|
-
def arcs
|
18
|
+
def arcs
|
19
|
+
domain | codomain
|
20
|
+
end
|
19
21
|
|
20
|
-
#
|
22
|
+
# Names of the places connected to the transition. The optional argument
|
23
|
+
# controls what is returned for unnamed instances, and works just like in
|
24
|
+
# <tt>Array#names</tt> method from <tt>y_support/name_magic</tt>:
|
25
|
+
# The default value (_nil_) returns _nil_, _true_ returns the instance itself,
|
26
|
+
# and _false_ drops the unnamed instances from the list altogether.
|
21
27
|
#
|
22
|
-
def aa
|
28
|
+
def aa arg=nil
|
29
|
+
arcs.names arg
|
30
|
+
end
|
31
|
+
|
32
|
+
# Arc (a place connected to this transition) identifier.
|
33
|
+
#
|
34
|
+
def arc id
|
35
|
+
place = place( id )
|
36
|
+
arcs.find { |p| p == place } or
|
37
|
+
fail TypeError, "No place #{id} connected to #{self}!"
|
38
|
+
end
|
23
39
|
|
24
40
|
# Marking of the domain places.
|
25
41
|
#
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
# Given the four transition types (TS, Ts, tS, ts), transition construction
|
4
|
-
# is not an easy task.
|
5
|
-
#
|
6
|
-
#
|
4
|
+
# is not an easy task. Having convenient constructor syntax is an important
|
5
|
+
# part of the functionality of the Transition class. Construction related
|
6
|
+
# functionality is thus gathered together in this mixin.
|
7
7
|
#
|
8
8
|
module YPetri::Transition::ConstructionConvenience
|
9
9
|
private
|
@@ -116,8 +116,8 @@ module YPetri::Transition::ConstructionConvenience
|
|
116
116
|
end
|
117
117
|
else # not a Proc, must guess user's intent
|
118
118
|
λ = if stoichiometric? then # standard mass action
|
119
|
-
|
120
|
-
|
119
|
+
fail TypeError, "With numeric rate, domain must not be given!" if
|
120
|
+
nn.has? :domain
|
121
121
|
__standard_mass_action__( λ )
|
122
122
|
else # constant closure
|
123
123
|
msg = "With numeric rate and no stoichio., codomain size must be 1!"
|
@@ -126,8 +126,8 @@ module YPetri::Transition::ConstructionConvenience
|
|
126
126
|
if dom == :missing then
|
127
127
|
dom = [] # Missing domain is natural here
|
128
128
|
else # but should it was supplied explicitly, it must be empty.
|
129
|
-
|
130
|
-
|
129
|
+
fail TypeError, "Rate is a number, but domain non-empty!" unless
|
130
|
+
domain.empty? if nn.has? :domain
|
131
131
|
end
|
132
132
|
end
|
133
133
|
end
|
@@ -191,8 +191,9 @@ module YPetri::Transition::ConstructionConvenience
|
|
191
191
|
# plain factors, assuming that if these places were not involved
|
192
192
|
# in the transition at all, the user would not be mentioning them.
|
193
193
|
case coeff
|
194
|
-
when 0
|
195
|
-
|
194
|
+
when 0 then marking * acc # coefficient 0 indicates plain factor
|
195
|
+
when -1 then marking * acc # for speed, 1 gets special treatment
|
196
|
+
else marking ** -coeff * acc end
|
196
197
|
end
|
197
198
|
end
|
198
199
|
end
|
@@ -214,7 +215,7 @@ module YPetri::Transition::ConstructionConvenience
|
|
214
215
|
else
|
215
216
|
# array of stoichiometry coefficients
|
216
217
|
msg = "With array-type stoichiometry, :codomain must be given!"
|
217
|
-
fail ArgumentError unless oo.has? :codomain
|
218
|
+
fail ArgumentError, msg unless oo.has? :codomain
|
218
219
|
[ oo[:codomain], Array( oo[:stoichiometry] ) ]
|
219
220
|
end
|
220
221
|
# enforce that stoichiometry is a collection of numbers
|
data/lib/y_petri/transition/t.rb
CHANGED
@@ -29,7 +29,7 @@ module YPetri::Transition::Type_t
|
|
29
29
|
msg = "Wrong output arity of the action closure of #{self}!"
|
30
30
|
fail TypeError, msg if act.size != codomain.size
|
31
31
|
codomain.each_with_index do |p, i|
|
32
|
-
note "adding action
|
32
|
+
note "adding action node no. #{i} to #{p}"
|
33
33
|
p.add note( "marking change", is: act.fetch( i ) )
|
34
34
|
end
|
35
35
|
end
|
@@ -45,4 +45,17 @@ module YPetri::Transition::Type_t
|
|
45
45
|
rescue YPetri::GuardError; false end
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
# Transition's firing under current simulation.
|
50
|
+
#
|
51
|
+
def fir simulation=world.simulation
|
52
|
+
simulation.net.State.Feature.Firing( self ) % simulation
|
53
|
+
end
|
54
|
+
|
55
|
+
# Prints the transition's action under current simulation.
|
56
|
+
#
|
57
|
+
def pa simulation=world.simulation, **nn
|
58
|
+
ff = simulation.net.State.Features.Delta( codomain, transitions: self )
|
59
|
+
( ff >> ff % simulation ).pretty_print_numeric_values **nn
|
60
|
+
end
|
48
61
|
end # class YPetri::Transition::Type_t
|
@@ -41,9 +41,13 @@ module YPetri::Transition::Types
|
|
41
41
|
end
|
42
42
|
alias s? nonstoichiometric?
|
43
43
|
|
44
|
-
# Does the transition's action depend on delta time?
|
44
|
+
# Does the transition's action depend on delta time? (Note that although A
|
45
|
+
# transitions are technically timeless, for pragmatic reasons, they are
|
46
|
+
# excluded from T/t classification, because they are generally handled
|
47
|
+
# differently in Petri net execution.)
|
45
48
|
#
|
46
49
|
def timed?
|
50
|
+
return nil if A?
|
47
51
|
@timed
|
48
52
|
end
|
49
53
|
alias T? timed?
|
@@ -51,6 +55,7 @@ module YPetri::Transition::Types
|
|
51
55
|
# Is the transition timeless? (Opposite of #timed?)
|
52
56
|
#
|
53
57
|
def timeless?
|
58
|
+
return nil if A?
|
54
59
|
not timed?
|
55
60
|
end
|
56
61
|
alias t? timeless?
|
data/lib/y_petri/transition.rb
CHANGED
@@ -53,6 +53,7 @@ require_relative 'transition/usable_without_world'
|
|
53
53
|
# 2. *Stoichiometricity*: _stoichiometric_ (*S*) / _nonstoichiometric_ (*s*)
|
54
54
|
#
|
55
55
|
# ==== Timedness
|
56
|
+
|
56
57
|
#
|
57
58
|
# * Timed transitions have _rate_ _closure_, whose result is to be multiplied
|
58
59
|
# by +Δtime+.
|
@@ -168,7 +169,7 @@ class YPetri::Transition
|
|
168
169
|
else Type_t end )
|
169
170
|
inform_upstream_places # that they have been connected
|
170
171
|
inform_downstream_places # that they have been connected
|
171
|
-
uncock # initialize in
|
172
|
+
uncock # initialize in uncocked state
|
172
173
|
end
|
173
174
|
|
174
175
|
# Domain, or 'upstream arcs', is a collection of places, whose marking
|
@@ -267,18 +268,14 @@ class YPetri::Transition
|
|
267
268
|
# return self
|
268
269
|
# end
|
269
270
|
|
270
|
-
#
|
271
|
-
#
|
272
|
-
def inspect
|
273
|
-
to_s
|
274
|
-
end
|
271
|
+
# Let's just leave this to NameMagic
|
275
272
|
|
276
|
-
# Conversion to a string.
|
277
|
-
#
|
278
|
-
def to_s
|
279
|
-
|
280
|
-
|
281
|
-
end
|
273
|
+
# # Conversion to a string.
|
274
|
+
# #
|
275
|
+
# def to_s
|
276
|
+
# "#<Transition: %s>" %
|
277
|
+
# "#{'%s ' % name if name}(#{type})#{' id:%s' % object_id unless name}"
|
278
|
+
# end
|
282
279
|
|
283
280
|
def place id
|
284
281
|
super rescue Place().instance( id )
|
data/lib/y_petri/version.rb
CHANGED
@@ -19,16 +19,16 @@ class YPetri::World
|
|
19
19
|
world.transition( id )
|
20
20
|
end
|
21
21
|
|
22
|
-
#
|
22
|
+
# Node instance identification.
|
23
23
|
#
|
24
|
-
def
|
24
|
+
def node id
|
25
25
|
begin
|
26
26
|
place( id )
|
27
27
|
rescue NameError, TypeError
|
28
28
|
begin
|
29
29
|
transition( id )
|
30
30
|
rescue NameError, TypeError => err
|
31
|
-
raise TypeError, "Unrecognized
|
31
|
+
raise TypeError, "Unrecognized node: #{id} (#{err})"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
# Workspace instance methods related to Petri net
|
4
|
-
# net instances).
|
3
|
+
# Workspace instance methods related to the Petri net aspect of YPetri
|
4
|
+
# (places, transitions, net instances).
|
5
5
|
#
|
6
|
-
module YPetri::World::
|
6
|
+
module YPetri::World::PetriNetAspect
|
7
7
|
# Instance initialization.
|
8
8
|
#
|
9
9
|
def initialize
|
@@ -58,4 +58,4 @@ module YPetri::World::PetriNetRelated
|
|
58
58
|
# Hook new transitions to add themselves magically to the :Top net.
|
59
59
|
Transition().new_instance_hook { |new_inst| net( :Top ) << new_inst }
|
60
60
|
end
|
61
|
-
end # module YPetri::World::
|
61
|
+
end # module YPetri::World::PetriNetAspect
|