lib/y_petri/net.rb in y_petri-2.1.51 vs lib/y_petri/net.rb in y_petri-2.2.0

- old
+ new

@@ -42,71 +42,113 @@ transitions.each &method( :include_transition ) param_class( { Simulation: YPetri::Simulation }, with: { net: self } ) end - # Includes a place in the net. Returns _true_ if successful, _false_ if the - # place is already included in the net. + # Includes a place in the receiver. Returns _true_ if successful, _false_ if + # the place is already included in the receiver net. # def include_place id pl = Place().instance( id ) return false if includes_place? pl true.tap { @places << pl } end - # Includes a transition in the net. Returns _true_ if successful, _false_ if - # the transition is already included in the net. The arcs of the transition - # being included may only connect to the places already in the net. + # Includes a transition in the receiver. Returns _true_ if successful, _false_ + # if the transition is already included in the net. The arcs of the transition + # being included may only connect to the places already in the receiver net. # def include_transition id tr = Transition().instance( id ) return false if includes_transition? tr msg = "Transition #{tr} has arcs to places outside #{self}!" fail msg unless tr.arcs.all? { |p| includes_place? p } true.tap { @transitions << tr } end - # Excludes a place from the net. Returns _true_ if successful, _false_ if the - # place was not found in the net. A place may not be excluded from the net so - # long as any transitions in the net connect to it. + # Excludes a place from the receiver. Returns _true_ if successful, _false_ + # if the place was not found in the receiver net. A place may not be excluded + # from the receiver so long as any transitions therein connect to it. # def exclude_place id pl = Place().instance( id ) msg = "Unable to exclude #{pl} from #{self}: Transition(s) depend on it!" fail msg if transitions.any? { |tr| tr.arcs.include? pl } false.tap { return true if @places.delete( pl ) } end - # Excludes a transition from the net. Returns _true_ if successful, _false_ if - # the transition was not found in the net. + # Excludes a transition from the receiver. Returns _true_ if successful, + # _false_ if the transition was not found in the receiver net. # def exclude_transition id tr = Transition().instance( id ) false.tap { return true if @transitions.delete( tr ) } end - # Includes an element in the net. + # Includes another net in the receiver net. Returns _true_ if successful + # (ie. if there was any change to the receiver net), _false_ if the receiver + # net already includes the argument net. # + def include_net id + net = Net().instance( id ) + p_rslt = net.pp.map { |p| include_place p }.reduce :| + t_rslt = net.tt.map { |t| include_transition t }.reduce :| + p_rslt || t_rslt + end + alias merge! include_net + + # Excludes another net from the receiver net. Returns _true_ if successful + # (ie. if there was any change to the receiver net), _false_ if the receiver + # net contained no element of the argument net. + # + def exclude_net id + net = Net().instance( id ) + t_rslt = net.tt.map { |t| exclude_transition t }.reduce :| + p_rslt = net.pp.map { |p| exclude_place p }.reduce :| + p_rslt || t_rslt + end + + # Includes an element (place or transition) in the net. + # def << element_id begin - element = self.class.place( element_id ) - type = :place + type, element = :place, self.class.place( element_id ) rescue NameError, TypeError begin - element = self.class.transition( element_id ) - type = :transition + type, element = :transition, self.class.transition( element_id ) rescue NameError, TypeError => err raise TypeError, "Current world contains no place or transition " + "identified by #{element_id}! (#{err})" end end - # Separated to minimize the code inside rescue clause: - if type == :place then include_place element - elsif type == :transition then include_transition element - else fail "Implementation error in YPetri::Net#<<!" end + case type # Factored out to minimize the code inside the rescue clause. + when :place then include_place( element ) + when :transition then include_transition( element ) + else fail "Implementation error!" end + return self # important to enable chaining, eg. foo_net << p1 << p2 << t1 end + # Creates a new net that contains all the places and transitions of both + # operands. + # + def + other + self.class.send( :new ).tap do |net| + net.merge! self + net.merge! other + end + end + + # Creates a new net that contains the places and transition of the receiver + # after excluding the second operand. + # + def - other + self.class.send( :new ).tap do |net| + net.merge! self + net.exclude_net other + end + end + # Is the net _functional_? # def functional? transitions.any? { |t| t.functional? } end @@ -131,13 +173,13 @@ end # Returns a string briefly describing the net. # def to_s - "#<Net: " + - ( name.nil? ? "%s" : "name: #{name}, %s" ) % - "#{pp.size rescue '∅'} places, #{tt.size rescue '∅'} transitions" + - ">" + form = "#<Net: %s>" + content = ( name.nil? ? "%s" : "name: #{name}, %s" ) % + "#{pp.size rescue '∅'} places, #{tt.size rescue '∅'} transitions" + form % content end # Inspect string of the instance. # def inspect