class YPetri::Simulation

Represents a Petri net simulation. Its concerns include the simulation method, simulation settings, initial values, marking clamps used during the simulation, guards etc. Its concerns do not include the Petri net domain model as such (places, transitions, arcs, transition functions…)

In a simulation, some places are designated as free (ie. their marking is free to be changed by firing of the net's transitions), while others are clamped (their marking is clamped by the simulation rather than changed by the transitions). For free places, initial marking has to be specified. For clamped places, marking clamps have to be specified. (For convenience, places may carry their own initial marking.)

Mixin providing collections of places / transitions to classes parametrized by an instance of YPetri::Simulation. Expects the includer classes to provide #simulation method returning the Simulation instance with which they are parametrized.

Basic nodes of a simulation, a mixin intended for YPetri::Simulation.

Manages the initial marking of a simulation.

Collection of marking clamps for YPetri::Simulation.

Manages the initial marking of a simulation.

Representation of a YPetri::Place inside a YPetri::Simulation instance.

Representation of a YPetri::Transition inside a YPetri::Simulation instance.

Constants

DEFAULT_SETTINGS

Attributes

A_direct_assignment_closure[R]

Parametrized subclasses.

TS_SM[R]

Parametrized subclasses.

TS_rate_closure[R]

Parametrized subclasses.

TS_stoichiometry_matrix[R]

Parametrized subclasses.

Ts_gradient_closure[R]

Parametrized subclasses.

guarded[R]

Parametrized subclasses.

guarded?[R]

Parametrized subclasses.

increment_marking_vector_closure[R]

Parametrized subclasses.

recorder[R]

Parametrized subclasses.

tS_SM[R]

Parametrized subclasses.

tS_firing_closure[R]

Parametrized subclasses.

tS_stoichiometry_matrix[R]

Parametrized subclasses.

ts_delta_closure[R]

Parametrized subclasses.

Public Class Methods

__new__(net: (fail ArgumentError, "No net supplied!"), **settings)
Alias for: new
new(net: (fail ArgumentError, "No net supplied!"), **settings) click to toggle source
# File lib/y_petri/simulation.rb, line 50
def new net: (fail ArgumentError, "No net supplied!"), **settings
  net.simulation **settings
end
Also aliased as: __new__
new(use_default_marking: true, guarded: false, marking_clamps: {}) click to toggle source

The basic simulation parameter is :net – a collection of places and transitions (a YPetri::Net instance) that is simulated. Other required arguments are :marking_clamps and :initial_marking (or +:marking – if no :initial_marking is supplied, :marking will be used in its stead). Even when the caller did not provide all the :initial_marking, there is an option of extracting them from the place instances themselves. This option, controlled by the named argument use_default_marking, is normally set to true, to turn it off, change it to false.

Simulation method is set by :method named argument, guarding is controlled by :guarded named argument (true/false). Simulations of timed nets are also timed. For a timed simulation, the constructor permits named arguments :time (alias :time_range), :step (simulation step size), and :sampling (sampling period), and requires that at least one of these named arguments be supplied.

# File lib/y_petri/simulation.rb, line 132
  def initialize use_default_marking: true,
                 guarded: false,
                 marking_clamps: {},
                 initial_marking: {},
                 marking: nil,
                 **settings
    param_class!( { PlacePS: PlaceRepresentation, # PS = parametrized subclass
                    PlacesPS: Places,
                    TransitionPS: TransitionRepresentation,
                    TransitionsPS: Transitions,
                    NodesPS: Nodes,
                    PlaceMapping: PlaceMapping,
                    InitialMarking: InitialMarking,
                    MarkingClamps: MarkingClamps,
                    MarkingVector: MarkingVector },
                  with: { simulation: self } )
    [ PlacePS(), TransitionPS() ].each &:namespace! # each serves as its namespace
    @guarded = guarded # TODO: Not operable as of now.
    @places = PlacesPS().load( net.places )
    @marking_clamps = MarkingClamps().load( marking_clamps )
    @initial_marking = if marking then
                         m = PlaceMapping().load( marking )
                         im = PlaceMapping().load( initial_marking )
                         InitialMarking().load( m.merge im )
                       else
                         InitialMarking().load( initial_marking )
                       end
    # Fill in the missing initial marking from the places' default marking.
    @places.send( :complete_initial_marking,
                  use_default_marking: use_default_marking )
    # Correspondence matrix free places --> all places
    @f2a = free_places.correspondence_matrix( places )
    # Correspondence matrix clamped places --> all places
    @c2a = clamped_places.correspondence_matrix( places )
    # Conditionally extend self depending on net's timedness.
    time_mentioned = settings[:time] || settings[:step] || settings[:sampling]
    if time_mentioned then extend Timed else extend Timeless end
    # Initialize the marking vector.
    @m_vector = MarkingVector().zero
    # Set up the collection of transitions.
    @transitions = TransitionsPS().load( net.transitions )
    # Set up stoichiometry matrices relative to free places.
    @tS_stoichiometry_matrix = transitions.tS.stoichiometry_matrix
    @TS_stoichiometry_matrix = transitions.TS.stoichiometry_matrix
    # Set up stoichiometry matrices relative to all places.
    @tS_SM = transitions.tS.SM
    @TS_SM = transitions.TS.SM
    # Call timedness-dependent #init subroutine.
    init **settings
    # Make time-independent closures.
    @ts_delta_closure = transitions.ts.delta_closure
    @tS_firing_closure = transitions.tS.firing_closure
    @A_direct_assignment_closure = transitions.A.direct_assignment_closure
    @increment_marking_vector_closure = m_vector.increment_closure
    # Make timed-only closures.
    if timed? then
      @Ts_gradient_closure = transitions.Ts.gradient_closure
      @TS_rate_closure = transitions.TS.rate_closure
    end
    # Reset.
    if marking then reset! marking: marking else reset! end
  end

  # Simulation settings.
  #
  def settings all=false
    return { method: simulation_method, guarded: guarded? } unless all == true
    { net: net,
      marking_clamps: marking_clamps.keys_to_source_places,
      initial_marking: initial_markings.keys_to_source_places
    }.update( settings )
  end

  # Returns a new simulation instance. Unless modified by arguments, the state
  # of the new instance is the same as the creator's. Arguments can partially or
  # wholly modify the attributes of the duplicate.
  #
  def dup( marking: marking(), recording: recording(), **named_args )
    named_args.reverse_merge! settings( true )
    self.class.new( named_args ).tap do |duplicate|
      duplicate.recorder.reset! recording: recording
      duplicate.m_vector.reset! case marking
                                when Hash then
                                  m_vector.to_hash_with_source_places
                                    .update( PlaceMapping().load( marking )
                                               .to_marking_vector
                                               .to_hash_with_source_places )
                                when Matrix, Array then marking
                                else marking.each.to_a end
    end
  end

  # Inspect string for this simulation.
  #
  def inspect
    to_s
  end

  # String representation of this simulation.
  #
  def to_s
    "#<Simulation: pp: %s, tt: %s, oid: %s>" % [ pp.size, tt.size, object_id ]
  end

  # Resets the simulation.
  #
  def reset! marking: nil, **named_args
    tap do
      marking ? m_vector.reset!( marking ) : m_vector.reset!
      recorder.reset!.alert!
    end
  end

  # Guards proposed marking delta.
  #
  def guard_Δ! Δ_free_places
    ary = ( marking_vector + F2A() * Δ_free_places ).column_to_a
    places.zip( ary ).each { |pl, proposed_m| pl.guard.( proposed_m ) }
  end

  # TODO: The method below does nothing except that it delegates extraction
  # of a set of features to Features class. Features understood in this way
  # are similar to ZZ dimensions.

  # Extract a prescribed set of features.
  #
  def get_features *args
    net.State.Features( *args ).extract_from( self )
  end
end

Public Instance Methods

dup( marking: marking(), recording: recording(), **named_args ) click to toggle source

Returns a new simulation instance. Unless modified by arguments, the state of the new instance is the same as the creator's. Arguments can partially or wholly modify the attributes of the duplicate.

# File lib/y_petri/simulation.rb, line 209
def dup( marking: marking(), recording: recording(), **named_args )
  named_args.reverse_merge! settings( true )
  self.class.new( named_args ).tap do |duplicate|
    duplicate.recorder.reset! recording: recording
    duplicate.m_vector.reset! case marking
                              when Hash then
                                m_vector.to_hash_with_source_places
                                  .update( PlaceMapping().load( marking )
                                             .to_marking_vector
                                             .to_hash_with_source_places )
                              when Matrix, Array then marking
                              else marking.each.to_a end
  end
end
firing(ids_of_tS_transitions=nil) click to toggle source

Returns the firing of the indicated tS transitions (all tS transitions, if no argument is given).

# File lib/y_petri/simulation.rb, line 91
def firing ids_of_tS_transitions=nil
  tt = tS_transitions()
  return firing tt if ids_of_tS_transitions.nil?
  tS_transitions( ids_of_tS_transitions ).map { |t|
    firing_vector_tS.column_to_a.fetch tt.index( t )
  }
end
get_features(*args) click to toggle source

Extract a prescribed set of features.

# File lib/y_petri/simulation.rb, line 258
def get_features *args
  net.State.Features( *args ).extract_from( self )
end
guard_Δ!(Δ_free_places) click to toggle source

Guards proposed marking delta.

# File lib/y_petri/simulation.rb, line 247
def guard_Δ! Δ_free_places
  ary = ( marking_vector + F2A() * Δ_free_places ).column_to_a
  places.zip( ary ).each { |pl, proposed_m| pl.guard.( proposed_m ) }
end
inspect() click to toggle source

Inspect string for this simulation.

# File lib/y_petri/simulation.rb, line 226
def inspect
  to_s
end
pfiring(ids=nil, gap: 0, precision: 4) click to toggle source

Pretty prints firing of the indicated tS transitions as hash with transition names as keys. Takes optional list of tS transition ids (first ordered arg.), and optional 2 named arguments (:gap and :precision), as in #pretty_print_numeric_values.

# File lib/y_petri/simulation.rb, line 111
def pfiring ids=nil, gap: 0, precision: 4
  t_firing( ids ).pretty_print_numeric_values( gap: gap, precision: precision )
end
reset!(marking: nil, **named_args) click to toggle source

Resets the simulation.

# File lib/y_petri/simulation.rb, line 238
def reset! marking: nil, **named_args
  tap do
    marking ? m_vector.reset!( marking ) : m_vector.reset!
    recorder.reset!.alert!
  end
end
settings(all=false) click to toggle source

Simulation settings.

# File lib/y_petri/simulation.rb, line 197
def settings all=false
  return { method: simulation_method, guarded: guarded? } unless all == true
  { net: net,
    marking_clamps: marking_clamps.keys_to_source_places,
    initial_marking: initial_markings.keys_to_source_places
  }.update( settings )
end
t_firing(ids=nil) click to toggle source

Firing of the indicated tS transitions (as hash with transition names as keys).

# File lib/y_petri/simulation.rb, line 102
def t_firing ids=nil
  tS_transitions( ids ).names( true ) >> firing( ids )
end
to_s() click to toggle source

String representation of this simulation.

# File lib/y_petri/simulation.rb, line 232
def to_s
  "#<Simulation: pp: %s, tt: %s, oid: %s>" % [ pp.size, tt.size, object_id ]
end