class YPetri::Net

Represents a _Petri net_: A collection of places and transitions. The connector arrows – called arcs in classical Petri net terminology – can be considered a property of transitions. Therefore in YPetri::Net, you won't find arcs as first-class citizens, but only as a synonym denoting nearest neighbors of nodes (places or transitions).

Public Class Methods

new( places: [], transitions: [] ) click to toggle source

Takes 2 arguments (:places and :transitions) and builds a net from them.

# File lib/y_petri/net.rb, line 38
def initialize( places: [], transitions: [] )
  param_class!( { State: State,
                  Simulation: YPetri::Simulation },
                with: { net: self } )
  @places, @transitions = [], []
  places.each &method( :include_place )
  transitions.each &method( :include_transition )
end
of(nodes) click to toggle source

Constructs a net containing a particular set of nodes.

# File lib/y_petri/net.rb, line 28
def of nodes
  new.tap { |inst| nodes.each { |node| inst << node } }
end

Public Instance Methods

+(other) click to toggle source

Creates a new net that contains all the places and transitions of both operands.

# File lib/y_petri/net.rb, line 135
def + other
  self.class.send( :new ).tap do |net|
    net.merge! self
    net.merge! other
  end
end
-(other) click to toggle source

Returns a new net that is the result of subtraction of the net given as argument from this net.

# File lib/y_petri/net.rb, line 145
def - other
  self.class.send( :new ).tap do |net|
    net.include_net self
    net.exclude_net other
  end
end
<<(node) click to toggle source

Includes a node (place or transition) in the receiver net.

# File lib/y_petri/net.rb, line 112
def << node
  begin
    type = :place
    place = self.class.place node
  rescue NameError, TypeError
    begin
      type = :transition
      transition = self.class.transition node
    rescue NameError, TypeError => err
      raise TypeError, "Current world contains no place or " +
        "transition #{node}! (#{err})"
    end
  end
  case type # Factored out to minimize the code inside the rescue clause.
  when :place then include_place( place )
  when :transition then include_transition( transition )
  else fail "Implementation error!" end
  return self # important to enable chaining, eg. foo_net << p1 << p2 << t1
end
==(other) click to toggle source

Networks are equal when their places and transitions are equal.

# File lib/y_petri/net.rb, line 173
def == other
  return false unless other.class_complies? self.class
  places == other.places && transitions == other.transitions
end
exclude_net(id) click to toggle source

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 node of the argument net.

# File lib/y_petri/net.rb, line 103
def exclude_net id
  net = Net().instance( id ) rescue YPetri::Net.instance( net )
  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
exclude_place(place) click to toggle source

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.

# File lib/y_petri/net.rb, line 72
def exclude_place place
  place = Place().instance( place )
  fail "Unable to exclude #{place} from #{self}: Transitions depend on it!" if
    transitions.any? { |transition| transition.arcs.include? place }
  false.tap { return true if @places.delete( place ) }
end
exclude_transition(transition) click to toggle source

Excludes a transition from the receiver. Returns true if successful, false if the transition was not found in the receiver net.

# File lib/y_petri/net.rb, line 82
def exclude_transition transition
  transition = Transition().instance( transition )
  false.tap { return true if @transitions.delete( transition ) }
end
functional?() click to toggle source

Is the net functional?

# File lib/y_petri/net.rb, line 154
def functional?
  transitions.any? &:functional?
end
include_net(net) click to toggle source

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.

# File lib/y_petri/net.rb, line 91
def include_net net
  net = Net().instance( net ) rescue YPetri::Net.instance( net )
  p_results = net.pp.map &method( :include_place )
  t_results = net.tt.map &method( :include_transition )
  ( p_results + t_results ).reduce :|
end
Also aliased as: merge!
include_place(place) click to toggle source

Includes a place in the receiver. Returns true if successful, false if the place is already included in the receiver net.

# File lib/y_petri/net.rb, line 50
def include_place place
  place = Place().instance( place )
  return false if include_place? place
  true.tap { @places << place }
end
include_transition(transition) click to toggle source

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.

# File lib/y_petri/net.rb, line 60
def include_transition transition
  transition = Transition().instance( transition )
  return false if include_transition? transition
  fail "Transition #{transition} has arcs to places outside #{self}!" unless
    transition.arcs.all? { |place| include_place? place }
  true.tap { @transitions << transition }
end
inspect() click to toggle source

Inspect string of the instance.

# File lib/y_petri/net.rb, line 189
def inspect
  to_s
end
merge!(net)
Alias for: include_net
new_simulation( **settings )
Alias for: simulation
simulation( **settings ) click to toggle source

Creates a new simulation from the net.

# File lib/y_petri/net.rb, line 166
def simulation( **settings )
  Simulation().__new__ **settings
end
Also aliased as: new_simulation
timed?() click to toggle source

Is the net timed?

# File lib/y_petri/net.rb, line 160
def timed?
  transitions.any? &:timed?
end
to_s() click to toggle source

Returns a string briefly describing the net.

# File lib/y_petri/net.rb, line 180
def to_s
  form = "#<Net: %s>"
  content = ( name.nil? ? "%s" : "name: #{name}, %s" ) %
    "#{pp.size rescue '∅'} places, #{tt.size rescue '∅'} transitions"
  form % content
end