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.
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