lib/y_petri/net/state/feature/firing.rb in y_petri-2.2.4 vs lib/y_petri/net/state/feature/firing.rb in y_petri-2.3.2
- old
+ new
@@ -1,36 +1,39 @@
# encoding: utf-8
-# Firing of a Petri net tS transition.
+# Firing of an S transition. (Firing is only defined on S transitions, whose
+# action can be computed as firing * stoichometry_vector_of_the_transition.)
#
class YPetri::Net::State::Feature::Firing < YPetri::Net::State::Feature
attr_reader :transition
class << self
# Customization of the Class#parametrize method.
#
def parametrize *args
Class.instance_method( :parametrize ).bind( self ).( *args ).tap do |ç|
- ç.instance_variable_set( :@instances,
- Hash.new do |hsh, id|
- case id
- when self then
- hsh[ id.transition ]
- when ç.net.Transition then
- t = begin
- ç.net.tS_transitions( [ id ] ).first
- rescue TypeError => err
- msg = "Transition #{id} not " +
- "recognized as tS transition in " +
- "net #{ç.net}! (%s)"
- raise TypeError, msg % err
- end
- hsh[ id ] = ç.__new__( t )
- else
- hsh[ ç.net.transition( id ) ]
- end
- end )
+ # First, prepare the hash of instances.
+ hsh = Hash.new do |hsh, id|
+ case id
+ when self then # missing key "id" is a Firing instance
+ hsh[ id.transition ]
+ when ç.net.Transition then
+ t = begin
+ ç.net.S_transitions( id ).first
+ rescue TypeError => err
+ msg = "Transition #{id} not " +
+ "recognized as tS transition in " +
+ "net #{ç.net}! (%s)"
+ raise TypeError, msg % err
+ end
+ hsh[ id ] = t.timed? ? ç.timed( t ) : ç.timeless( t )
+ else
+ hsh[ ç.net.transition( id ) ]
+ end
+ end
+ # And then, assign it to the :@instances variable.
+ ç.instance_variable_set :@instances, hsh
end
end
attr_reader :instances
@@ -43,35 +46,68 @@
# Alias of #new method.
#
def of id
new id
end
+
+ # Expects a single timed transition and constructs a timed firing feature.
+ #
+ def timed id
+ __new__( net.T_tt( id ).first )
+ .tap { |i| i.instance_variable_set :@timed, true }
+ end
+
+ # Expects a single timeless transition and constructs a timeless firing
+ # feature.
+ #
+ def timeless id
+ __new__( net.t_tt( id ).first )
+ .tap { |i| i.instance_variable_set :@timed, false }
+ end
end
# The constructor of a marking feature takes exactly one argument (transition
# identifier).
#
def initialize transition
@transition = net.transition( transition )
end
- # Extracts the receiver marking feature from the argument. This can be
- # typically a simulation instance.
+ # Extracts the value of this feature from the target (eg. a simulation).
+ # If the receiver firing feature is timed, this method requires an additional
+ # named argument +:delta_time+, alias +:Δt+.
#
- def extract_from arg, **nn
+ def extract_from arg, **named_args
case arg
when YPetri::Simulation then
- arg.send( :tS_transitions, [ transition ] ).first.firing
+ if timed? then
+ arg.send( :TS_transitions, transition ).first
+ .firing( named_args.must_have :delta_time, syn!: :Δt )
+ else
+ arg.send( :tS_transitions, transition ).first.firing
+ end
else
fail TypeError, "Argument type not supported!"
end
end
+ # Is the delta feature timed?
+ #
+ def timed?
+ @timed
+ end
+
+ # Opposite of +#timed?+.
+ #
+ def timeless?
+ ! timed?
+ end
+
# Type of this feature.
#
def type
- :flux
+ :firing
end
# A string briefly describing the firing feature.
#
def to_s
@@ -86,7 +122,14 @@
# Inspect string of the firing feature.
#
def inspect
"<Feature::Firing of #{transition.name ? transition.name : transition}>"
+ end
+
+ # Firing features are equal if they are of equal PS and refer
+ # to the same transition.
+ #
+ def == other
+ other.is_a? net.State.Feature.Firing and transition == other.transition
end
end # YPetri::Net::State::Feature::Firing