Class: YPetri::Simulation::MarkingVector

Inherits:
Matrix
  • Object
show all
Extended by:
Dependency
Defined in:
lib/y_petri/simulation/marking_vector.rb,
lib/y_petri/simulation/marking_vector/access.rb

Overview

A mixin to YPetri::Simulation.

Defined Under Namespace

Modules: Access

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Dependency

delegate_to_simulation!

Methods inherited from Matrix

#assign_at_indices_closure, column_vector_access_code, column_vector_assignment_code, column_vector_increment_by_array_code, column_vector_increment_code, #increment_at_indices_closure

Class Attribute Details

.annotationObject (readonly)

Returns the value of attribute annotation.



12
13
14
# File 'lib/y_petri/simulation/marking_vector.rb', line 12

def annotation
  @annotation
end

Class Method Details

.[](arg) ⇒ Object

Constructs a marking vector from a hash places >> values, or from an array, in which case, it is assumed that the marking vector corresponds to all the places in the simulation.

TODO: I don’t like having to write MarkingVector[ [ 1, 2, 3 ] ] instead of MarkingVector[ 1, 2, 3 ], but I accepted and endorsed it long time ago as a necessary tax for being able to distinguish between the user meaning to supply no arguments and the user meaning to supply empty vector.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/y_petri/simulation/marking_vector.rb', line 24

def [] arg
  case arg
  when Hash then annotated_with( arg.keys )[ arg.values ]
  when Array then
    if annotation then
      fail ArgumentError, "The size of the argument (#{arg.size}) does " +
        "not match the annotation size (#{annotation.size})!" unless
        msg unless arg.size == annotation.size
      column_vector( arg )
    else
      annotated_with( places )[ arg ]
    end
  else
    self[ arg.each.to_a ]
  end
end

.annotated_with(places) ⇒ Object

Returns a subclass of self annotated with the supplied array of places.



43
44
45
46
# File 'lib/y_petri/simulation/marking_vector.rb', line 43

def annotated_with places
  annot = annotation ? annotation.subset( places ) : Places( places )
  Class.new self do @annotation = annot end
end

.starting(places = nil) ⇒ Object

Without arguments, constructs the starting marking vector for all the places, using either initial values, or clamp values. Optionally, an array of places or place ids can be supplied, for which the starting vector is returned.



53
54
55
56
57
58
59
60
# File 'lib/y_petri/simulation/marking_vector.rb', line 53

def starting places=nil
  if places.nil? then
    return starting( places() ) if annotation.nil?
    self[ annotation.map { |p| p.free? ? p.initial_marking : p.clamp } ]
  else
    annotated_with( places ).starting
  end
end

.zero(places = nil) ⇒ Object

Without arguments, constructs a zero marking vector for all the places. Optionally, an array of places or places ids can be supplied, for which the zero vector is returned.



66
67
68
# File 'lib/y_petri/simulation/marking_vector.rb', line 66

def zero places=nil
  starting( places ) * 0
end

Instance Method Details

#annotationObject

Annotation.



127
128
129
# File 'lib/y_petri/simulation/marking_vector.rb', line 127

def annotation
  self.class.annotation
end

#fetch(id) ⇒ Object

Access of the vector elements.



121
122
123
# File 'lib/y_petri/simulation/marking_vector.rb', line 121

def fetch id
  self[ index( id ), 0  ]
end

#increment_closureObject

Builds the assignment closure.



174
175
176
177
# File 'lib/y_petri/simulation/marking_vector.rb', line 174

def increment_closure
  indices_of_free_places = annotation.free.map { |p| annotation.index p }
  increment_at_indices_closure( indices: indices_of_free_places )
end

#index(id) ⇒ Object

Index of a place.



133
134
135
136
137
138
139
140
# File 'lib/y_petri/simulation/marking_vector.rb', line 133

def index id
  if id.is_a? Numeric then
    fail RangeError, "Numeric index must be within 0..#{size}" unless
      ( 0..size ) === id
  else
    annotation.index place( id )
  end
end

#pretty_print(*args) ⇒ Object Also known as: pp

Pretty-prints the marking vector.



181
182
183
# File 'lib/y_petri/simulation/marking_vector.rb', line 181

def pretty_print *args
  to_h.pretty_print_numeric_values *args
end

#reset!(arg = self.class.starting) ⇒ Object

Whole vector is reset to a given collection of values. If no argument is given, starting vector is used.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/y_petri/simulation/marking_vector.rb', line 98

def reset! arg=self.class.starting
  case arg
  when Hash then
    # Hash is first converted into a PlaceMapping instance (mp).
    mp = simulation.PlaceMapping().load( arg )
    # Updated marking vector is constructed using reliable methods
    # self.class.starting and self#set.
    updated = mp.each_with_object self.class.starting do |(place, value), mv|
      mv.set place, value
    end
    # Updated marking vector is then converted into an array and #reset! method
    # is called upon it again to actually perform in-place update of this vector.
    # TODO: The above is slightly inefficient -- constructing a new vector when
    # in-place modification seems a better solution. But if it works, it's a
    # strong reason to not fix it until we are in the optimization stage.
    reset! updated.column_to_a
  else # array arg assumed
    arg.each.to_a.zip( annotation ).map { |value, place| set place, value }
  end
end

#select(places, &block) ⇒ Object

Expects an array of places or place ids, and creates a subset of this marking vector. Alternatively, a block can be supplied that performs the places selection similarly to Enumerable#select.



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/y_petri/simulation/marking_vector.rb', line 77

def select places, &block
  if block_given? then
    fail ArgumentError, "Arguments not allowed if block given!" unless
      place_ids.empty?
    select annotation.select &block
  else
    pp = places( *places )
    annotated_subcl = self.class.annotated_with( pp )
    annotated_subcl[ pp.map { |p| fetch p } ]
  end
end

#set(id, value) ⇒ Object

Modifying the vector elements.



91
92
93
# File 'lib/y_petri/simulation/marking_vector.rb', line 91

def set id, value
  self[ index( id ), 0 ] = value
end

#sizeObject

Marking vector size – depends on the annotation.



144
145
146
# File 'lib/y_petri/simulation/marking_vector.rb', line 144

def size
  annotation.size
end

#to_aObject

Converts the marking vector (which is a column vector) into an array.



150
151
152
# File 'lib/y_petri/simulation/marking_vector.rb', line 150

def to_a
  ( 0..size - 1 ).map { |i| self[ i, 0 ] }
end

#to_hObject

Converts the marking vector into a hash annotation_names >> values.



162
163
164
# File 'lib/y_petri/simulation/marking_vector.rb', line 162

def to_h
  annotation.names( true ) >> to_a
end

#to_hashObject

Converts the marking vector into a hash annotation >> values.



156
157
158
# File 'lib/y_petri/simulation/marking_vector.rb', line 156

def to_hash
  annotation >> to_a
end

#to_hash_with_source_placesObject

Converts the marking vector into a hash source places >> values.



168
169
170
# File 'lib/y_petri/simulation/marking_vector.rb', line 168

def to_hash_with_source_places
  annotation.sources >> to_a
end