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
@@ -1,8 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
# Basic elements of a simulation, a mixin intended for YPetri::Simulation.
|
4
|
-
#
|
5
3
|
class YPetri::Simulation
|
4
|
+
# The class in which places' marking is stored insid a simulation.
|
5
|
+
#
|
6
6
|
class MarkingVector < Matrix
|
7
7
|
★ Dependency
|
8
8
|
|
@@ -20,10 +20,10 @@ class YPetri::Simulation
|
|
20
20
|
when Hash then annotated_with( arg.keys )[ arg.values ]
|
21
21
|
when Array then
|
22
22
|
if annotation then
|
23
|
-
|
24
|
-
"
|
25
|
-
|
26
|
-
column_vector arg
|
23
|
+
fail ArgumentError, "The size of the argument (#{arg.size}) does " +
|
24
|
+
"not match the annotation size (#{annotation.size})!" unless
|
25
|
+
msg unless arg.size == annotation.size
|
26
|
+
column_vector( arg )
|
27
27
|
else
|
28
28
|
annotated_with( places )[ args ]
|
29
29
|
end
|
@@ -32,57 +32,55 @@ class YPetri::Simulation
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
# Returns a subclass of self annotated with the supplied places.
|
35
|
+
# Returns a subclass of self annotated with the supplied array of places.
|
36
36
|
#
|
37
|
-
def annotated_with
|
38
|
-
annot =
|
39
|
-
annotation.subset place_ids
|
40
|
-
else
|
41
|
-
places( place_ids )
|
42
|
-
end
|
37
|
+
def annotated_with places
|
38
|
+
annot = annotation ? annotation.subset( places ) : Places( places )
|
43
39
|
Class.new self do @annotation = annot end
|
44
40
|
end
|
45
41
|
|
46
|
-
# Without arguments, constructs the starting marking vector for all
|
47
|
-
# using either initial values, or clamp values. Optionally,
|
48
|
-
#
|
42
|
+
# Without arguments, constructs the starting marking vector for all the
|
43
|
+
# places, using either initial values, or clamp values. Optionally, an
|
44
|
+
# array of places or place ids can be supplied, for which the starting
|
45
|
+
# vector is returned.
|
49
46
|
#
|
50
|
-
def starting
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
self[ annotation.map &st ]
|
47
|
+
def starting places=nil
|
48
|
+
if places.nil? then
|
49
|
+
return starting places() if annotation.nil?
|
50
|
+
self[ annotation.map { |p| p.free? ? p.initial_marking : p.clamp } ]
|
55
51
|
else
|
56
|
-
annotated_with(
|
52
|
+
annotated_with( places ).starting
|
57
53
|
end
|
58
54
|
end
|
59
55
|
|
60
|
-
# Without arguments, constructs a zero marking vector for all places.
|
61
|
-
# Optionally, places can be
|
62
|
-
# returned.
|
56
|
+
# Without arguments, constructs a zero marking vector for all the places.
|
57
|
+
# Optionally, an array of places or places ids can be supplied, for which
|
58
|
+
# the zero vector is returned.
|
63
59
|
#
|
64
|
-
def zero
|
65
|
-
starting(
|
60
|
+
def zero places=nil
|
61
|
+
starting( places ) * 0
|
66
62
|
end
|
67
63
|
end
|
68
64
|
|
69
65
|
delegate :simulation, to: "self.class"
|
70
66
|
|
71
|
-
#
|
67
|
+
# Expects an array of places or place ids, and creates a subset of this
|
68
|
+
# marking vector. Alternatively, a block can be supplied that performs
|
69
|
+
# the places selection similarly to +Enumerable#select+.
|
72
70
|
#
|
73
|
-
def select
|
71
|
+
def select places, &block
|
74
72
|
if block_given? then
|
75
|
-
|
76
|
-
|
77
|
-
select annotation.select
|
73
|
+
fail ArgumentError, "Arguments not allowed if block given!" unless
|
74
|
+
place_ids.empty?
|
75
|
+
select annotation.select &block
|
78
76
|
else
|
79
|
-
pp = places(
|
77
|
+
pp = places( *places )
|
80
78
|
annotated_subcl = self.class.annotated_with( pp )
|
81
79
|
annotated_subcl[ pp.map { |p| fetch p } ]
|
82
80
|
end
|
83
81
|
end
|
84
82
|
|
85
|
-
# Modifying the vector
|
83
|
+
# Modifying the vector nodes.
|
86
84
|
#
|
87
85
|
def set id, value
|
88
86
|
self[ index( id ), 0 ] = value
|
@@ -104,7 +102,7 @@ class YPetri::Simulation
|
|
104
102
|
end
|
105
103
|
end
|
106
104
|
|
107
|
-
# Access of the vector
|
105
|
+
# Access of the vector nodes.
|
108
106
|
#
|
109
107
|
def fetch id
|
110
108
|
self[ index( id ), 0 ]
|
@@ -166,8 +164,8 @@ class YPetri::Simulation
|
|
166
164
|
|
167
165
|
# Pretty-prints the marking vector.
|
168
166
|
#
|
169
|
-
def pretty_print
|
170
|
-
to_h.pretty_print_numeric_values
|
167
|
+
def pretty_print *args
|
168
|
+
to_h.pretty_print_numeric_values *args
|
171
169
|
end
|
172
170
|
alias pp pretty_print
|
173
171
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Representation of a YPetri::Place inside a YPetri::Simulation instance.
|
4
|
+
#
|
5
|
+
class YPetri::Simulation::NodeRepresentation
|
6
|
+
★ NameMagic
|
7
|
+
★ YPetri::Simulation::Dependency
|
8
|
+
|
9
|
+
attr_reader :source # source place
|
10
|
+
|
11
|
+
delegate :simulation, to: "self.class"
|
12
|
+
|
13
|
+
# Expect a single YPetri place as an argument.
|
14
|
+
#
|
15
|
+
def initialize net_node_id
|
16
|
+
@source = net.node( net_node_id )
|
17
|
+
end
|
18
|
+
|
19
|
+
# Tweak the #to_s method to give the node representations the inspect string
|
20
|
+
# of type #<Name>.
|
21
|
+
#
|
22
|
+
def to_s
|
23
|
+
"#<#{super}>"
|
24
|
+
end
|
25
|
+
end # class YPetri::Simulation::NodeRepresentation
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Simulation mixin providing access to nodes (places / transitions). Also see
|
4
|
+
# mixins +Places::Access+ and +Transitions::Access+.
|
5
|
+
#
|
6
|
+
class YPetri::Simulation::Nodes
|
7
|
+
module Access
|
8
|
+
# Does a node belong to the simulation?
|
9
|
+
#
|
10
|
+
def includes?( id )
|
11
|
+
includes_place?( id ) || includes_transition?( id )
|
12
|
+
end
|
13
|
+
alias include? includes?
|
14
|
+
|
15
|
+
# Node of the simulation belonging to the net. Each simulation has its
|
16
|
+
# representations of places and transitions, which are based on the places
|
17
|
+
# and transitions of the underlying net. This method takes one argument,
|
18
|
+
# which (place, place name, transition, or transition name) and returns the
|
19
|
+
# corresponding node of the underlying net.
|
20
|
+
#
|
21
|
+
def n( node )
|
22
|
+
node( node ).source
|
23
|
+
end
|
24
|
+
|
25
|
+
# Nodes of the simulation (belonging to the net). Expects a single array of
|
26
|
+
# nodes (places / transitions) or node ids and returns an array of the
|
27
|
+
# corresponding nodes in the underlying net.
|
28
|
+
#
|
29
|
+
def Nn( array )
|
30
|
+
Nodes( array ).sources
|
31
|
+
end
|
32
|
+
|
33
|
+
# Without arguments, returns all the nodes of the underlying net. Otherwise,
|
34
|
+
# it accepts an arbitrary number of nodes or node ids as arguments, and
|
35
|
+
# returns an array of the corresponding nodes of the underlying net.
|
36
|
+
#
|
37
|
+
def nn( *nodes )
|
38
|
+
nodes( *nodes ).sources
|
39
|
+
end
|
40
|
+
|
41
|
+
# Names of the simulation's nodes. Arguments, if any, are treated
|
42
|
+
# analogically to the +#nodes+ method.
|
43
|
+
#
|
44
|
+
def nnn *nodes
|
45
|
+
nnn( *nodes ).names
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
# Node instance identification.
|
51
|
+
#
|
52
|
+
def node( node )
|
53
|
+
return place node if include_place? node
|
54
|
+
return transition node if include_transition? node
|
55
|
+
fail TypeError, "No node #{node} in the simulation!"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Expects a single array of nodes (places / transitions) or node ids and
|
59
|
+
# returns an array of the corresponding node instances.
|
60
|
+
#
|
61
|
+
def Nodes( array )
|
62
|
+
# NOTE: At the moment, the Simulation instance does not have a
|
63
|
+
# parametrized subclass of Simulation::Nodes class, the following
|
64
|
+
# statement is thus made to return a plain array of elements.
|
65
|
+
Nodes().load array.map &method( :node )
|
66
|
+
end
|
67
|
+
|
68
|
+
# Without arguments, returns all the nodes (places / transitions) of the
|
69
|
+
# simulation. Otherwise, it accepts an arbitrary number of nodes or node ids
|
70
|
+
# as arguments, and returns an array of the corresponding nodes of the
|
71
|
+
# simulation.
|
72
|
+
#
|
73
|
+
def nodes( *nodes )
|
74
|
+
return places + transitions if nodes.empty?
|
75
|
+
Nodes( nodes )
|
76
|
+
end
|
77
|
+
end # module Access
|
78
|
+
end # class YPetri::Simulation::Nodes
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
# Basic elements of a simulation, a mixin intended for YPetri::Simulation.
|
4
|
-
#
|
5
3
|
class YPetri::Simulation
|
6
|
-
|
4
|
+
# An array of simulation owned places and/or transitions.
|
5
|
+
#
|
6
|
+
class Nodes < Array
|
7
7
|
★ Dependency
|
8
8
|
|
9
9
|
class << self
|
@@ -16,28 +16,29 @@ class YPetri::Simulation
|
|
16
16
|
|
17
17
|
delegate :simulation, to: "self.class"
|
18
18
|
|
19
|
-
# Loads
|
19
|
+
# Loads nodes to this collection.
|
20
20
|
#
|
21
|
-
def load
|
22
|
-
|
21
|
+
def load nodes
|
22
|
+
nodes.each{ |node| push node }
|
23
23
|
end
|
24
24
|
|
25
25
|
# Creates a subset of this collection (of the same class).
|
26
26
|
#
|
27
|
-
def subset
|
27
|
+
def subset nodes=nil, &block
|
28
28
|
if block_given? then
|
29
|
-
|
30
|
-
|
29
|
+
fail ArgumentError, "If block given, arguments not allowed!" unless
|
30
|
+
nodes.nil?
|
31
31
|
self.class.load select( &block )
|
32
32
|
else
|
33
|
-
|
34
|
-
|
33
|
+
fail ArgumentError, "A collection or a block expected!" if nodes.nil?
|
34
|
+
nn = Nodes( nodes )
|
35
|
+
nn.all? { |node| include? node } or
|
35
36
|
fail TypeError, "All subset elements must be in the collection."
|
36
|
-
self.class.load(
|
37
|
+
self.class.load( nn )
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
|
-
# Returns an array of the
|
41
|
+
# Returns an array of the node sources (nodes in the underlying net).
|
41
42
|
#
|
42
43
|
def sources
|
43
44
|
map &:source
|
@@ -3,10 +3,11 @@
|
|
3
3
|
# Representation of a YPetri::Place inside a YPetri::Simulation instance.
|
4
4
|
#
|
5
5
|
class YPetri::Simulation
|
6
|
-
class PlaceRepresentation <
|
6
|
+
class PlaceRepresentation < NodeRepresentation
|
7
7
|
attr_reader :quantum
|
8
8
|
|
9
|
-
# Index
|
9
|
+
# Index.
|
10
|
+
#
|
10
11
|
def m_vector_index
|
11
12
|
places.index( self )
|
12
13
|
end
|
@@ -21,32 +22,32 @@ class YPetri::Simulation
|
|
21
22
|
# Setter of clamp.
|
22
23
|
#
|
23
24
|
def clamp=( value )
|
24
|
-
simulation.set_marking_clamp(
|
25
|
+
simulation.set_marking_clamp( self, to: value )
|
25
26
|
end
|
26
27
|
|
27
28
|
# Setter of initial marking.
|
28
29
|
#
|
29
30
|
def initial_marking=( value )
|
30
|
-
simulation.set_initial_marking(
|
31
|
+
simulation.set_initial_marking( self, to: value )
|
31
32
|
end
|
32
33
|
|
33
34
|
# Marking clamp value (or nil, if the place is clamped).
|
34
35
|
#
|
35
36
|
def marking_clamp
|
36
|
-
simulation.marking_clamp
|
37
|
+
simulation.marking_clamp( self ) if clamped?
|
37
38
|
end
|
38
39
|
alias clamp marking_clamp
|
39
40
|
|
40
41
|
# Initial marking value (or nil, if the place is free).
|
41
42
|
#
|
42
43
|
def initial_marking
|
43
|
-
simulation.initial_marking
|
44
|
+
simulation.initial_marking( self ) if free?
|
44
45
|
end
|
45
46
|
|
46
47
|
# Is the place free in the current simulation?
|
47
48
|
#
|
48
49
|
def free?
|
49
|
-
simulation.
|
50
|
+
simulation.initial_markings.places.include? self
|
50
51
|
end
|
51
52
|
|
52
53
|
# Is the place clamped in the current simulation?
|
@@ -1,121 +1,140 @@
|
|
1
|
-
#encoding: utf-8
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
3
|
# Simulation mixin providing access to places.
|
4
4
|
#
|
5
5
|
class YPetri::Simulation::Places
|
6
6
|
module Access
|
7
|
-
# With no arguments, a reader of
|
8
|
-
# free places and all places. If argument is given, it is assumed
|
9
|
-
# a column vector, and multiplication is performed.
|
7
|
+
# With no arguments, acts as a reader of f2a -- the correspondence matrix
|
8
|
+
# between free places and all places. If argument is given, it is assumed
|
9
|
+
# to be a column vector, and multiplication with f2a is performed.
|
10
10
|
#
|
11
11
|
def f2a arg=nil
|
12
|
-
|
12
|
+
arg.nil? ? @f2a : @f2a * arg
|
13
13
|
end
|
14
14
|
|
15
|
-
# With no arguments, a reader of
|
16
|
-
# clamped places and all places. If argument is given, it is assumed
|
17
|
-
# a column vector, and multiplication is performed.
|
15
|
+
# With no arguments, acts as a reader of c2a -- the correspondence matrix
|
16
|
+
# between clamped places and all places. If argument is given, it is assumed
|
17
|
+
# to be a column vector, and multiplication with c2a is performed.
|
18
18
|
#
|
19
19
|
def c2a arg=nil
|
20
|
-
|
20
|
+
arg.nil? ? @c2a : @c2a * arg
|
21
21
|
end
|
22
22
|
|
23
23
|
# Does a place belong to the simulation?
|
24
24
|
#
|
25
|
-
def includes_place?
|
26
|
-
true.tap { begin; place
|
27
|
-
rescue NameError, TypeError
|
25
|
+
def includes_place? place
|
26
|
+
true.tap { begin; place place; rescue NameError, TypeError
|
28
27
|
return false
|
29
28
|
end }
|
30
29
|
end
|
31
30
|
alias include_place? includes_place?
|
32
31
|
|
33
|
-
#
|
32
|
+
# Net's place.
|
34
33
|
#
|
35
|
-
def p(
|
36
|
-
place(
|
34
|
+
def p( place )
|
35
|
+
place( place ).source
|
37
36
|
end
|
38
37
|
|
39
|
-
#
|
38
|
+
# Makes it so that when "places" is abbreviated to "pp", places of the
|
39
|
+
# underlying net are returned rather than simulation's place representations.
|
40
40
|
#
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
chain Pp: :Places,
|
42
|
+
pp: :places,
|
43
|
+
Free_pp: :Free_places,
|
44
|
+
free_pp: :free_places,
|
45
|
+
Clamped_pp: :Clamped_places,
|
46
|
+
clamped_pp: :clamped_places,
|
47
|
+
&:sources
|
44
48
|
|
45
|
-
|
46
|
-
|
47
|
-
def free_pp( ids=nil )
|
48
|
-
free_places( ids ).sources
|
49
|
-
end
|
49
|
+
alias free_Pp Free_pp
|
50
|
+
alias clamped_Pp Clamped_pp
|
50
51
|
|
51
|
-
#
|
52
|
+
# Makes it so that +Pn+/+pn+ means "names of places", and that when message
|
53
|
+
# "n" + place_type is sent to the simulation, it returns names of the places
|
54
|
+
# of the specified type.
|
52
55
|
#
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
chain Pn: :Pt,
|
57
|
+
pn: :pp,
|
58
|
+
nfree: :free_places,
|
59
|
+
nclamped: :clamped_places do |r| r.names( true ) end
|
56
60
|
|
57
|
-
# Places' names. Arguments, if any, are treated as in +#places+ method.
|
58
|
-
#
|
59
|
-
def pn( ids=nil )
|
60
|
-
places( ids ).names
|
61
|
-
end
|
62
|
-
|
63
|
-
# Names of free places. Arguments are handled as with +#free_places+.
|
64
|
-
#
|
65
|
-
def nfree ids=nil
|
66
|
-
free_places( ids ).names
|
67
|
-
end
|
68
61
|
alias free_pn nfree
|
69
|
-
|
70
|
-
# Names of free places. Arguments are handled as with +#clamped_places+.
|
71
|
-
#
|
72
|
-
def nclamped ids=nil
|
73
|
-
clamped_places( ids ).names
|
74
|
-
end
|
75
62
|
alias clamped_pn nclamped
|
76
63
|
|
77
64
|
protected
|
78
65
|
|
79
66
|
# Place instance identification.
|
80
67
|
#
|
81
|
-
def place(
|
82
|
-
begin
|
83
|
-
Place().instance( id )
|
84
|
-
rescue NameError, TypeError
|
68
|
+
def place( place )
|
69
|
+
begin; Place().instance( place ); rescue NameError, TypeError
|
85
70
|
begin
|
86
|
-
|
87
|
-
places.find { |
|
88
|
-
Place().instance(
|
71
|
+
place = net.place( place )
|
72
|
+
places.find { |place_rep| place_rep.source == place } ||
|
73
|
+
Place().instance( place.name )
|
89
74
|
rescue NameError, TypeError => msg
|
90
|
-
raise
|
91
|
-
|
92
|
-
|
75
|
+
raise # FIXME: This raise needs to be here in order for the current
|
76
|
+
# tests to pass (they expect NameError, while the raise below would
|
77
|
+
# raise TypeError). But it is not clear to me anymore why the tests
|
78
|
+
# require NameError in the first place. Gotta look into it.
|
79
|
+
raise TypeError, "The argument #{place} (class #{place.class}) does " +
|
80
|
+
"not identify a place instance! (#{msg})"
|
93
81
|
end
|
94
82
|
end
|
95
83
|
end
|
96
84
|
|
97
|
-
#
|
98
|
-
#
|
85
|
+
# Constructs an instance of @Places parametrized subclass. Expects a single
|
86
|
+
# array of places or place ids and returns an array of corresponding place
|
87
|
+
# representations in the simulation. Note that the includer of the
|
88
|
+
# +Places::Access+ module normally overloads :Places message in such way,
|
89
|
+
# that even without an argument, it does not fail, but returns the @Places
|
90
|
+
# parametrized subclass itself.
|
91
|
+
#
|
92
|
+
def Places( array )
|
93
|
+
# Kernel.p array
|
94
|
+
Places().load array.map &method( :place )
|
95
|
+
end
|
96
|
+
|
97
|
+
# Without arguments, returns all the place representations in the simulation.
|
98
|
+
# Otherwise, it accepts an arbitrary number of places or place ids as
|
99
|
+
# arguments, and a corresponding array of place representations.
|
100
|
+
#
|
101
|
+
def places( *places )
|
102
|
+
return @places if places.empty?
|
103
|
+
Places( places )
|
104
|
+
end
|
105
|
+
|
106
|
+
# Expects a single array of free places or place ids and returns an array of
|
107
|
+
# the corresponding free place representations in the simulation.
|
108
|
+
#
|
109
|
+
def Free_places( array )
|
110
|
+
places.free.subset( array )
|
111
|
+
end
|
112
|
+
alias free_Places Free_places
|
113
|
+
|
114
|
+
# Without arguments, returns all free places of the simulation. Otherwise, it
|
115
|
+
# accepts an arbitrary number of free places or place ids as arguments, and
|
116
|
+
# returns an array of the corresponding free places of the simulation.
|
99
117
|
#
|
100
|
-
def
|
101
|
-
return
|
102
|
-
|
118
|
+
def free_places( *free_places )
|
119
|
+
return places.free if free_places.empty?
|
120
|
+
Free_places( free_places )
|
103
121
|
end
|
104
122
|
|
105
|
-
#
|
106
|
-
#
|
123
|
+
# Expects a single array of clamped places or place ids and returns an array
|
124
|
+
# of the corresponding clamped place representations in the simulation.
|
107
125
|
#
|
108
|
-
def
|
109
|
-
|
110
|
-
places.free.subset( ids )
|
126
|
+
def Clamped_places( array )
|
127
|
+
places.clamped.subset( array )
|
111
128
|
end
|
129
|
+
alias clamped_Places Clamped_places
|
112
130
|
|
113
|
-
#
|
114
|
-
# places
|
131
|
+
# Withoud arguments, returns all clamped places of the simulation. Otherwise,
|
132
|
+
# it accepts an arbitrary number of clamped places or place ids as arguments,
|
133
|
+
# and returns and array of the correspondingg clamped places.
|
115
134
|
#
|
116
|
-
def clamped_places
|
117
|
-
return places.clamped if
|
118
|
-
|
135
|
+
def clamped_places( *clamped_places )
|
136
|
+
return places.clamped if clamped_places.empty?
|
137
|
+
Clamped_places( clamped_places )
|
119
138
|
end
|
120
139
|
end # module Access
|
121
140
|
end # class YPetri::Simulation::Places
|
@@ -1,25 +1,23 @@
|
|
1
|
-
#encoding: utf-8
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
3
|
# A mixin with place type selectors.
|
4
4
|
#
|
5
|
-
class YPetri::Simulation
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end # class Places
|
25
|
-
end # class YPetri::Simulation
|
5
|
+
class YPetri::Simulation::Places
|
6
|
+
module Types
|
7
|
+
# Subset of free places, if any.
|
8
|
+
#
|
9
|
+
def free
|
10
|
+
( @Type_free ||= Class.new( self.class ).tap do |klass|
|
11
|
+
klass.class_exec { include Type_free }
|
12
|
+
end ).load subset( &:free? )
|
13
|
+
end
|
14
|
+
|
15
|
+
# Subset of clamped places, if any.
|
16
|
+
#
|
17
|
+
def clamped
|
18
|
+
( @Type_clamped ||= Class.new( self.class ).tap do |klass|
|
19
|
+
klass.class_exec { include Type_clamped }
|
20
|
+
end ).load subset( &:clamped? )
|
21
|
+
end
|
22
|
+
end # Types
|
23
|
+
end # class YPetri::Simulation::Places
|