class Petrinet::Net

Represents a Petri Net in a particular state. Instances of this class are immutable. The following methods return new instances:

The internal representation uses a VASS - en.wikipedia.org/wiki/Vector_addition_system A good explanation of how this works with Petri Nets is here: github.com/bitwrap/bitwrap-io/blob/master/whitepaper.md

Attributes

prefire_transition_name[R]

Public Class Methods

build(&proc) click to toggle source
# File lib/petrinet/net.rb, line 22
def self.build(&proc)
  builder = Builder.new
  proc.call(builder)
  builder.net
end
from_pnml(xml) click to toggle source
# File lib/petrinet/net.rb, line 17
def self.from_pnml(xml)
  builder = PnmlBuilder.new(xml)
  builder.net
end
new(state_vector, place_index_by_place_name, transition_vectors_by_transition_name, prefire_transition_name = nil) click to toggle source
# File lib/petrinet/net.rb, line 30
def initialize(state_vector, place_index_by_place_name, transition_vectors_by_transition_name, prefire_transition_name = nil)
  @state_vector = state_vector
  @place_index_by_place_name = place_index_by_place_name
  @transition_vectors_by_transition_name = transition_vectors_by_transition_name
  @prefire_transition_name = prefire_transition_name
  freeze
end

Public Instance Methods

fire(transition_name) click to toggle source
# File lib/petrinet/net.rb, line 48
def fire(transition_name)
  new_state_vector = new_state_vector(transition_name)
  self.class.new(new_state_vector, @place_index_by_place_name, @transition_vectors_by_transition_name)
end
fireable() click to toggle source
# File lib/petrinet/net.rb, line 66
def fireable
  result = Set.new
  @transition_vectors_by_transition_name.keys.each do |transition_name|
    begin
      fire(transition_name)
      result.add(transition_name)
    rescue => ignore
      # It wasn't fireable - ignore it
    end
  end
  result
end
fireable?(transition_name) click to toggle source
# File lib/petrinet/net.rb, line 57
def fireable?(transition_name)
  begin
    new_state_vector(transition_name)
    true
  rescue
    false
  end
end
mark(marking) click to toggle source

Marks the petri net and returns a new instance

# File lib/petrinet/net.rb, line 39
def mark(marking)
  new_state_vector = Array.new(@state_vector.size, 0)
  marking.each do |place_name, token_count|
    index = @place_index_by_place_name[place_name]
    new_state_vector[index] = token_count
  end
  self.class.new(new_state_vector, @place_index_by_place_name, @transition_vectors_by_transition_name)
end
prefire(transition_name) click to toggle source
# File lib/petrinet/net.rb, line 53
def prefire(transition_name)
  self.class.new(@state_vector, @place_index_by_place_name, @transition_vectors_by_transition_name, transition_name)
end
to_animated_gif(transition_names, gif_path) click to toggle source
# File lib/petrinet/net.rb, line 84
def to_animated_gif(transition_names, gif_path)
  builder = AnimatedGifBuilder.new(self)
  builder.write(transition_names, gif_path)
end
to_svg() click to toggle source
# File lib/petrinet/net.rb, line 79
def to_svg
  builder = GraphvizBuilder.new(self, @transition_vectors_by_transition_name, @place_index_by_place_name.invert, @state_vector)
  builder.svg
end

Private Instance Methods

new_state_vector(transition_name) click to toggle source
# File lib/petrinet/net.rb, line 91
def new_state_vector(transition_name)
  transition_vectors = @transition_vectors_by_transition_name[transition_name]
  raise "Unknown transition: #{transition_name}. Known transitions: #{@transition_vectors_by_transition_name.keys}" if transition_vectors.nil?
  transition_vectors.reduce(@state_vector) do |state_vector, transition_vector|
    v = state_vector.zip(transition_vector).map { |s, t| s + t }
    raise "Cannot fire: #{transition_name}" unless valid?(v)
    v
  end
end
valid?(state_vector) click to toggle source
# File lib/petrinet/net.rb, line 101
def valid?(state_vector)
  !(state_vector.any? { |s| s.negative? })
end