y_petri 2.2.4 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +675 -0
  3. data/README.md +6 -3
  4. data/Rakefile +1 -1
  5. data/lib/y_petri/agent/{petri_net_related.rb → petri_net_aspect.rb} +34 -10
  6. data/lib/y_petri/agent/{simulation_related.rb → simulation_aspect.rb} +49 -34
  7. data/lib/y_petri/agent.rb +5 -5
  8. data/lib/y_petri/core/guarded.rb +24 -0
  9. data/lib/y_petri/core/timed/euler.rb +4 -8
  10. data/lib/y_petri/core/timed/gillespie.rb +11 -17
  11. data/lib/y_petri/core/timed/methods.rb +23 -0
  12. data/lib/y_petri/core/timed/pseudo_euler.rb +10 -13
  13. data/lib/y_petri/core/timed/quasi_euler.rb +9 -8
  14. data/lib/y_petri/core/timed/runge_kutta.rb +10 -18
  15. data/lib/y_petri/core/timed.rb +6 -14
  16. data/lib/y_petri/core/timeless/methods.rb +15 -0
  17. data/lib/y_petri/core/timeless/pseudo_euler.rb +4 -8
  18. data/lib/y_petri/core/timeless.rb +9 -4
  19. data/lib/y_petri/core.rb +44 -42
  20. data/lib/y_petri/net/data_set.rb +246 -142
  21. data/lib/y_petri/net/node_access.rb +282 -0
  22. data/lib/y_petri/net/own_state.rb +14 -4
  23. data/lib/y_petri/net/state/feature/assignment.rb +123 -0
  24. data/lib/y_petri/net/state/feature/delta.rb +55 -35
  25. data/lib/y_petri/net/state/feature/firing.rb +68 -25
  26. data/lib/y_petri/net/state/feature/flux.rb +9 -2
  27. data/lib/y_petri/net/state/feature/gradient.rb +36 -19
  28. data/lib/y_petri/net/state/feature/marking.rb +10 -5
  29. data/lib/y_petri/net/state/feature.rb +105 -11
  30. data/lib/y_petri/net/state/features/record.rb +144 -99
  31. data/lib/y_petri/net/state/features.rb +327 -200
  32. data/lib/y_petri/net/state.rb +48 -82
  33. data/lib/y_petri/net/visualization.rb +1 -1
  34. data/lib/y_petri/net.rb +62 -47
  35. data/lib/y_petri/place/arcs.rb +44 -0
  36. data/lib/y_petri/place/features.rb +115 -0
  37. data/lib/y_petri/place.rb +62 -29
  38. data/lib/y_petri/simulation/dependency.rb +31 -67
  39. data/lib/y_petri/simulation/feature_set.rb +1 -1
  40. data/lib/y_petri/simulation/initial_marking/access.rb +42 -26
  41. data/lib/y_petri/simulation/marking_clamps/access.rb +22 -17
  42. data/lib/y_petri/simulation/marking_clamps.rb +0 -2
  43. data/lib/y_petri/simulation/marking_vector/access.rb +102 -40
  44. data/lib/y_petri/simulation/marking_vector.rb +35 -37
  45. data/lib/y_petri/simulation/matrix.rb +1 -1
  46. data/lib/y_petri/simulation/node_representation.rb +25 -0
  47. data/lib/y_petri/simulation/nodes/access.rb +78 -0
  48. data/lib/y_petri/simulation/{elements.rb → nodes.rb} +14 -13
  49. data/lib/y_petri/simulation/place_mapping.rb +2 -2
  50. data/lib/y_petri/simulation/place_representation.rb +8 -7
  51. data/lib/y_petri/simulation/places/access.rb +89 -70
  52. data/lib/y_petri/simulation/places/free.rb +1 -1
  53. data/lib/y_petri/simulation/places/types.rb +20 -22
  54. data/lib/y_petri/simulation/places.rb +23 -18
  55. data/lib/y_petri/simulation/recorder.rb +23 -18
  56. data/lib/y_petri/simulation/timed/recorder.rb +19 -11
  57. data/lib/y_petri/simulation/timed.rb +93 -29
  58. data/lib/y_petri/simulation/timeless/recorder.rb +11 -6
  59. data/lib/y_petri/simulation/timeless.rb +13 -3
  60. data/lib/y_petri/simulation/transition_representation/A.rb +24 -4
  61. data/lib/y_petri/simulation/transition_representation/S.rb +11 -1
  62. data/lib/y_petri/simulation/transition_representation/T.rb +1 -1
  63. data/lib/y_petri/simulation/transition_representation/Ts.rb +1 -1
  64. data/lib/y_petri/simulation/transition_representation/a.rb +1 -1
  65. data/lib/y_petri/simulation/transition_representation/s.rb +12 -1
  66. data/lib/y_petri/simulation/transition_representation/t.rb +1 -1
  67. data/lib/y_petri/simulation/transition_representation/tS.rb +1 -1
  68. data/lib/y_petri/simulation/transition_representation/ts.rb +1 -1
  69. data/lib/y_petri/simulation/transition_representation/types.rb +1 -1
  70. data/lib/y_petri/simulation/transition_representation.rb +4 -11
  71. data/lib/y_petri/simulation/transitions/A.rb +17 -2
  72. data/lib/y_petri/simulation/transitions/S.rb +1 -1
  73. data/lib/y_petri/simulation/transitions/T.rb +1 -1
  74. data/lib/y_petri/simulation/transitions/Ts.rb +6 -5
  75. data/lib/y_petri/simulation/transitions/a.rb +1 -1
  76. data/lib/y_petri/simulation/transitions/access.rb +195 -168
  77. data/lib/y_petri/simulation/transitions/s.rb +1 -1
  78. data/lib/y_petri/simulation/transitions/t.rb +1 -1
  79. data/lib/y_petri/simulation/transitions/tS.rb +1 -1
  80. data/lib/y_petri/simulation/transitions/ts.rb +1 -1
  81. data/lib/y_petri/simulation/transitions/types.rb +1 -1
  82. data/lib/y_petri/simulation/transitions.rb +5 -7
  83. data/lib/y_petri/simulation.rb +84 -90
  84. data/lib/y_petri/transition/A.rb +8 -2
  85. data/lib/y_petri/transition/T.rb +25 -2
  86. data/lib/y_petri/transition/arcs.rb +19 -3
  87. data/lib/y_petri/transition/construction_convenience.rb +11 -10
  88. data/lib/y_petri/transition/t.rb +14 -1
  89. data/lib/y_petri/transition/types.rb +6 -1
  90. data/lib/y_petri/transition.rb +9 -12
  91. data/lib/y_petri/version.rb +1 -1
  92. data/lib/y_petri/world/dependency.rb +3 -3
  93. data/lib/y_petri/world/{petri_net_related.rb → petri_net_aspect.rb} +4 -4
  94. data/lib/y_petri/world/simulation_aspect.rb +352 -0
  95. data/lib/y_petri/world.rb +4 -4
  96. data/lib/y_petri.rb +1 -1
  97. data/test/agent_test.rb +2 -1
  98. data/test/examples/demonstrator.rb +4 -1
  99. data/test/examples/demonstrator_2.rb +5 -0
  100. data/test/examples/demonstrator_4.rb +6 -5
  101. data/test/examples/example_2.rb +2 -0
  102. data/test/examples/manual_examples.rb +4 -4
  103. data/test/net_test.rb +457 -54
  104. data/test/place_test.rb +11 -7
  105. data/test/simulation_test.rb +358 -331
  106. data/test/transition_test.rb +11 -10
  107. data/test/world_test.rb +2 -0
  108. data/test/y_petri_test.rb +2 -1
  109. data/y_petri.gemspec +24 -18
  110. metadata +71 -17
  111. data/LICENSE +0 -22
  112. data/lib/y_petri/net/element_access.rb +0 -239
  113. data/lib/y_petri/simulation/element_representation.rb +0 -20
  114. data/lib/y_petri/simulation/elements/access.rb +0 -57
  115. data/lib/y_petri/transition/type.rb +0 -103
  116. data/lib/y_petri/transition/type_information.rb +0 -103
  117. 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
- msg = "The size of the argument (#{arg.size}) does not " +
24
- "correspond to the annotation size (#{annotation.size})!"
25
- fail ArgumentError, msg unless arg.size == annotation.size
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 place_ids
38
- annot = if annotation then
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 places,
47
- # using either initial values, or clamp values. Optionally, places can be
48
- # specified, for which the starting vector is returned.
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 place_ids=nil
51
- st = -> p { p.free? ? p.initial_marking : p.clamp } # starting value
52
- if place_ids.nil? then
53
- return starting places if annotation.nil?
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( place_ids ).starting
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 specified, for which the zero vector is
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( place_ids=nil )
65
- starting( place_ids ) * 0
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
- # Creates a subset of this marking vector.
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 place_ids, &block
71
+ def select places, &block
74
72
  if block_given? then
75
- msg = "If block is given, arguments are not allowed!"
76
- fail ArgumentError, msg unless place_ids.empty?
77
- select annotation.select( &block )
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( place_ids )
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 elements.
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 elements.
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
@@ -1,4 +1,4 @@
1
- #encoding: utf-8
1
+ # encoding: utf-8
2
2
 
3
3
  require 'matrix'
4
4
 
@@ -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
- class Elements < Array
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 elements to this collection.
19
+ # Loads nodes to this collection.
20
20
  #
21
- def load elements
22
- elements.each{ |e| push e }
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 element_ids=nil, &block
27
+ def subset nodes=nil, &block
28
28
  if block_given? then
29
- msg = "If block is given, arguments are not allowed!"
30
- fail ArgumentError, msg unless element_ids.nil?
29
+ fail ArgumentError, "If block given, arguments not allowed!" unless
30
+ nodes.nil?
31
31
  self.class.load select( &block )
32
32
  else
33
- ee = elements( element_ids )
34
- ee.all? { |e| include? e } or
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( ee )
37
+ self.class.load( nn )
37
38
  end
38
39
  end
39
40
 
40
- # Returns an array of the element sources (elemens in the original net).
41
+ # Returns an array of the node sources (nodes in the underlying net).
41
42
  #
42
43
  def sources
43
44
  map &:source
@@ -44,8 +44,8 @@ class YPetri::Simulation
44
44
 
45
45
  # Fetches the value for a place.
46
46
  #
47
- def of place_id
48
- fetch place( place_id )
47
+ def fetch place_id
48
+ super place( place_id )
49
49
  end
50
50
 
51
51
  # Deletes the value for a place.
@@ -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 < ElementRepresentation
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( of: self, to: value )
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( of: self, to: value )
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 of: self if clamped?
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[ self ] if free?
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.initial_marking.places.include? self
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 @f2a -- the correspondence matrix between
8
- # free places and all places. If argument is given, it is assumed to be
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
- if arg.nil? then @f2a else @f2a * arg end
12
+ arg.nil? ? @f2a : @f2a * arg
13
13
  end
14
14
 
15
- # With no arguments, a reader of @c2a -- the correspondence matrix between
16
- # clamped places and all places. If argument is given, it is assumed to be
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
- if arg.nil? then @c2a else @c2a * arg end
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? id
26
- true.tap { begin; place id
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
- # Place of the simulation (belonging to the net).
32
+ # Net's place.
34
33
  #
35
- def p( id )
36
- place( id ).source
34
+ def p( place )
35
+ place( place ).source
37
36
  end
38
37
 
39
- # Places of the simulation (belonging to the net).
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
- def pp( ids=nil )
42
- places( ids ).sources
43
- end
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
- # Free places of the simulation (belonging to the net).
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
- # Clamped places of the simulation (belonging to the net).
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
- def clamped_pp( ids=nil )
54
- clamped_places( ids ).sources
55
- end
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( id )
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
- pl = net.place( id )
87
- places.find { |p_rep| p_rep.source == pl } ||
88
- Place().instance( pl.name )
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
- raise TypeError, "The argument #{id} (class #{id.class}) does not identify a " +
92
- "place instance! (#{msg})"
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
- # Without arguments, returns all the places. If arguments are given, they
98
- # are converted to places before being returned.
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 places( ids=nil )
101
- return @places if ids.nil?
102
- Places().load( ids.map { |id| place id } )
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
- # Free places. If arguments are given, they must be identify free places,
106
- # and are converted to them.
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 free_places ids=nil
109
- return places.free if ids.nil?
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
- # Clamped places. If arguments are given, they must be identify clamped
114
- # places, and are converted to them.
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 ids=nil
117
- return places.clamped if ids.nil?
118
- places.clamped.subset( ids )
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,4 +1,4 @@
1
- #encoding: utf-8
1
+ # encoding: utf-8
2
2
 
3
3
  # A mixin for collections of free places.
4
4
  #
@@ -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
- class Places < Elements
7
- module Types
8
- # Subset of free places, if any.
9
- #
10
- def free
11
- ( @Type_free ||= Class.new( self.class ).tap do |klass|
12
- klass.class_exec { include Type_free }
13
- end ).load subset( &:free? )
14
- end
15
-
16
- # Subset of clamped places, if any.
17
- #
18
- def clamped
19
- ( @Type_clamped ||= Class.new( self.class ).tap do |klass|
20
- klass.class_exec { include Type_clamped }
21
- end ).load subset( &:clamped? )
22
- end
23
- end # Types
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