lib/y_petri/net/state.rb in y_petri-2.2.4 vs lib/y_petri/net/state.rb in y_petri-2.3.2
- old
+ new
@@ -1,129 +1,95 @@
# encoding: utf-8
-# An array whose elements correspond to the full marking of the net's places.
-#
+# An array whose elements represent marking of places of a +YPetri::Net+.
+#
class YPetri::Net::State < Array
require_relative 'state/feature'
require_relative 'state/features'
class << self
- # Customization of the parametrize method for the State class: Its
- # dependents Feature and Features (feature set class) are also parametrized.
+ # Customization of the parametrize method for the State class: Its dependents
+ # Feature and Features (feature set class) are also parametrized.
#
def parametrize net: ( fail ArgumentError, "No owning net!" )
Class.new( self ).tap do |ç|
ç.define_singleton_method :net do net end
- ç.param_class( { Feature: Feature,
- Features: Features },
- with: { State: ç } )
+ ç.param_class!( { Feature: Feature,
+ Features: Features },
+ with: { State: ç } )
end
end
- delegate :Marking,
- :Firing,
- :Gradient,
- :Flux,
- :Delta,
- to: "Feature()"
-
# Returns the feature identified by the argument.
- #
- def feature *id
- fail ArgumentError, "No feature identifier!" if id.empty?
- case id.first
- when Feature() then id.first
- when Feature then id.first.class.new( id.first )
- else
- msg = "Malformed feature identifier!"
- fail ArgumentError, msg unless id.size == 1 and id.first.is_a? Hash
- ꜧ = id.first
- fail ArgumentError, msg unless ꜧ.size == 1
- key, val = ꜧ.keys.first, ꜧ.values.first
- recognized = :marking, :firing, :gradient, :flux, :delta
- msg = "Unrecognized feature: #{key}"
- fail ArgumentError, msg unless recognized.include? key
- # And now, with everything clean...
+ #
+ def Feature arg=nil, **named_args
+ case arg
+ when Feature() then arg
+ when Feature then arg.class.new( arg )
+ when nil then
+ key, val = named_args.first
case key
- when :marking then Marking( val )
- when :firing then Firing( val )
- when :flux then Flux( val )
- when :gradient then Gradient( *val )
- when :delta then Delta( *val )
+ when :marking then Feature().Marking( val )
+ when :firing then Feature().Firing( val )
+ when :flux then Feature().Flux( val )
+ when :gradient then Feature().Gradient( *val )
+ when :delta then Feature().Delta( *val )
+ when :assignment then Feature().Assignment( val )
+ else fail ArgumentError, "Unrecognized feature: #{key}!"
end
+ else
+ Feature().infer_from_node( arg )
end
end
- # If the argument is an array of features, or another Features instance,
- # a feature set based on this array is returned. But the real purpose of
- # this method is to allow hash-type argument, with keys +:marking+,
- # +:firing+, +:gradient+, +:flux+ and +:delta+, specifying the respective
- # features. For +:marking+, an array of places (or Marking features) is
- # expected. For +:firing+ and +:flux+, an array of transitions (or Firing
- # / Flux features) is expected. For +:gradient+ and +:delta+, a hash value
- # is expected, containing keys +:places+ and +:transitions+, specifying
- # for which place set / transition set should gradient / delta features
- # be constructed. More in detail, values supplied under keys +:marking+,
- # +:firing+, +:gradient+, +:flux+ and +:delta+ are delegated to
- # +Features.marking+, +Features.firing+, +Features.gradient+ and
- # +Features.flux+ methods, and their results are joined into a single
- # feature set.
+ # A constructor of a +Features+ instance. Note that the message +:Features+
+ # called without arguments is intercepted by a singleton method and returns
+ # the parametrized subclass of +State::Features+ owned by this class.
#
- def features arg
- case arg
- when Features(), Array then Features().new( arg )
- else # the real job of the method
- marking = arg[:marking] || []
- firing = arg[:firing] || [] # array of tS transitions
- gradient = arg[:gradient] || [ [], transitions: [] ]
- flux = arg[:flux] || [] # array of TS transitions
- delta = arg[:delta] || [ [], transitions: [] ]
- [ Features().marking( marking ),
- Features().firing( firing ),
- Features().gradient( *gradient ),
- Features().flux( flux ),
- Features().delta( *delta ) ].reduce :+
- end
+ # This method may accept a single array-type argument, constructing a feature
+ # set out of it. Alternatively, the method may accept named arguments:
+ # +:marking+, +:firing+, +:gradient+, +:flux+, +:delta+, and +:assignment+,
+ # specifying the a single (possibly mixed) feature set.
+ #
+ def Features array=nil, **named_args
+ Features()[ *array, **named_args ]
end
+ end # class << self
- delegate :marking, :firing, :gradient, :flux, :delta, to: "Features()"
- end
-
- # For non-parametrized vesion of the class, the class instance variables
- # hold the non-parametrized dependent classes.
+ # For non-parametrized vesion of the class, should it ever be used in such way,
+ # the class instance variables hold the non-parametrized dependent classes.
#
@Feature, @Features = Feature, Features
delegate :net,
- :Feature,
- :Features,
- :features,
- :marking, :firing, :gradient, :flux, :delta,
+ :Feature, # Note that as syntactic salt, specific methods
+ :Features, # #marking, #firing, #gradient, #flux etc. are
+ :features, # not delegated to self.class.
to: "self.class"
- # Given a set of clamped places, this method outputs a Record instance
+ # Given a set of clamped places, this method outputs a +Record+ instance
# containing the marking of the free places (complementary to the supplied
# set of clamped places). I no set of clamped places is supplied, it is
# considered empty.
#
- def to_record clamped_places=[]
+ def to_record clamped_places
free_places = case clamped_places
when Hash then to_record( clamped_places.keys )
else
- free_places = places - places( clamped_places )
+ places - places( clamped_places )
end
features( marking: free_places ).Record.load markings( free_places )
end
# Marking of a single given place in this state.
#
- def marking place_id
- self[ places.index place( place_id ) ]
+ def marking place
+ self[ net.places.index net.place( place ) ]
end
- # Returns an array of markings of particular places in this state..
+ # Expects an arbitrary number of places or place ids, and returns an array
+ # of their markings as per the receiver +State+ instance.
#
- def markings place_ids=nil
- return markings( places ) if place_ids.nil?
- place_ids.map &:marking
+ def markings *places
+ places.map &method( :marking )
end
end # YPetri::Net::State