# encoding: utf-8
# Workspace instance methods related to the Simulation aspect of YPetri
# (stored marking collections, clamp collections, inital marking collections,
# management of simulations...)
#
module YPetri::World::SimulationAspect
# Collections of clamps, initial marking vectors, and simulation settings.
#
attr_reader :clamp_collections,
:initial_marking_collections,
:simulation_settings_collections
# Instance initialization.
#
def initialize
@simulations = {} # { simulation => its settings }
@clamp_collections = { Base: {} } # { collection name => clamp hash }
@initial_marking_collections = { Base: {} } # { collection name => im hash }
@simulation_settings_collections = # { collection name => ss hash }
{ Base: ( YPetri::Simulation::DEFAULT_SETTINGS.call
.update YPetri::Simulation::Timed::DEFAULT_SETTINGS.call ) }
super
end
# Hash of simulation instances and their settings.
#
def simulations
@simulations
end
# Clamp collection names.
#
def clamp_collection_names
@clamp_collections.keys
end
alias ncc clamp_collection_names
# Initial marking collection names.
#
def initial_marking_collection_names
@initial_marking_collections.keys
end
alias nimc initial_marking_collection_names
# Simulation settings collection names.
#
def simulation_settings_collection_names
@simulation_settings_collections.keys
end
alias nssc simulation_settings_collection_names
# Clamp collection identified by the argument.
#
def clamp_collection name=:Base
@clamp_collections[name]
end
alias cc clamp_collection
# Marking collection identified by the argument.
#
def initial_marking_collection name=:Base
@initial_marking_collections[name]
end
alias imc initial_marking_collection
# Simulation settings collection specified by the argument.
#
def simulation_settings_collection name=:Base
@simulation_settings_collections[name]
end
alias ssc simulation_settings_collection
# Creates a new clamp collection. If collection identifier is not given,
# resets :Base clamp collection to new values.
#
def set_clamp_collection( name=:Base, clamp_hash )
@clamp_collections[name] = clamp_hash
end
alias set_cc set_clamp_collection
# Creates a new initial marking collection. If collection identifier is not
# given, resets :Base initial marking collection to new values.
#
def set_initial_marking_collection( name=:Base, initial_marking_hash )
@initial_marking_collections[name] = initial_marking_hash
end
alias set_imc set_initial_marking_collection
# Creates a new simulation settings collection. If collection identifier is
# not given, resets :Base simulation settings collection to new values.
#
def set_simulation_settings_collection( name=:Base, sim_set_hash )
@simulation_settings_collections[name] = sim_set_hash
end
alias set_ssc set_simulation_settings_collection
# Presents a simulation specified by the argument, which must be a hash with
# four items: :net, :clamp_collection, :inital_marking_collection and
# :simulation_settings_collection.
#
def simulation settings={}
key = case settings
when ~:may_have then # it is a hash or equivalent
settings.may_have :net
settings.may_have :cc, syn!: :clamp_collection
settings.may_have :imc, syn!: :initial_marking_collection
settings.may_have :ssc, syn!: :simulation_settings_collection
{ net: net( settings[:net] || self.Net::Top ), # the key
cc: settings[:cc] || :Base,
imc: settings[:imc] || :Base,
ssc: settings[:ssc] || :Base }
else # use the unprocessed argument itself as the key
settings
end
@simulations[ key ]
end
# Makes a new timed simulation. Named arguments for this method are the same
# as for TimedSimulation#new, but in addition, :name can be supplied.
#
# To create a simulation, simulation settings collection, initial marking
# collection, and clamp collection have to be specified. A place clamp,
# is a fixed value, at which the marking is held. Similarly, initial
# marking is the marking, which a free place receives at the beginning.
# Free places are those, that are not clamped. After initialization, marking
# of free places is allowed to change as the transition fire.
#
# For example, having places :P1..:P5, clamped :P1, :P2 can be written as eg.:
#
# * clamps = { P1: 4, P2: 5 }
#
# Places :P3, :P4, :P5 are free. Their initial marking has to be
# specified, which can be written as eg.:
#
# * initial_markings = { P3: 1, P4: 2, P5: 3 }
#
# As for simulation settings, their exact nature depends on the simulation
# method. For default Euler method, there are 3 important parameters:
# - step_size,
# - sampling_period,
# - target_time
#
# For example, default simulation settings are:
#
# * default_ss = { step_size: 0.1, sampling_period: 5, target_time: 60 }
#
def new_simulation( net: Net()::Top, **nn )
net_inst = net( net )
nn.may_have :cc, syn!: :clamp_collection
nn.may_have :imc, syn!: :initial_marking_collection
nn.may_have :ssc, syn!: :simulation_settings_collection
cc_id = nn.delete( :cc ) || :Base
imc_id = nn.delete( :imc ) || :Base
ssc_id = nn.delete( :ssc ) || :Base
# Construct the simulation key:
key = if nn.has? :name, syn!: :ɴ then # explicit key (name)
nn[:name]
else # constructed key
{}.merge( net: net_inst,
cc: cc_id,
imc: imc_id,
ssc: ssc_id )
.merge( nn )
end
# Let's clarify what we got so far.
sim_settings = ssc( ssc_id )
mc_hash = cc( cc_id )
im_hash = imc( imc_id )
# Create and return the simulation
sim = net_inst.simulation **sim_settings.merge( initial_marking: im_hash,
marking_clamps: mc_hash
).merge( nn )
@simulations[ key ] = sim
end
end # module YPetri::World::SimulationAspect
# encoding: utf-8
# Workspace instance methods related to the Simulation aspect of YPetri
# (stored marking collections, clamp collections, inital marking collections,
# management of simulations...)
#
module YPetri::World::SimulationAspect
# Collections of clamps, initial marking vectors, and simulation settings.
#
attr_reader :clamp_collections,
:initial_marking_collections,
:simulation_settings_collections
# Instance initialization.
#
def initialize
@simulations = {} # { simulation => its settings }
@clamp_collections = { Base: {} } # { collection name => clamp hash }
@initial_marking_collections = { Base: {} } # { collection name => im hash }
@simulation_settings_collections = # { collection name => ss hash }
{ Base: ( YPetri::Simulation::DEFAULT_SETTINGS.call
.update YPetri::Simulation::Timed::DEFAULT_SETTINGS.call ) }
super
end
# Hash of simulation instances and their settings.
#
def simulations
@simulations
end
# Clamp collection names.
#
def clamp_collection_names
@clamp_collections.keys
end
alias ncc clamp_collection_names
# Initial marking collection names.
#
def initial_marking_collection_names
@initial_marking_collections.keys
end
alias nimc initial_marking_collection_names
# Simulation settings collection names.
#
def simulation_settings_collection_names
@simulation_settings_collections.keys
end
alias nssc simulation_settings_collection_names
# Clamp collection identified by the argument.
#
def clamp_collection name=:Base
@clamp_collections[name]
end
alias cc clamp_collection
# Marking collection identified by the argument.
#
def initial_marking_collection name=:Base
@initial_marking_collections[name]
end
alias imc initial_marking_collection
# Simulation settings collection specified by the argument.
#
def simulation_settings_collection name=:Base
@simulation_settings_collections[name]
end
alias ssc simulation_settings_collection
# Creates a new clamp collection. If collection identifier is not given,
# resets :Base clamp collection to new values.
#
def set_clamp_collection( name=:Base, clamp_hash )
@clamp_collections[name] = clamp_hash
end
alias set_cc set_clamp_collection
# Creates a new initial marking collection. If collection identifier is not
# given, resets :Base initial marking collection to new values.
#
def set_initial_marking_collection( name=:Base, initial_marking_hash )
@initial_marking_collections[name] = initial_marking_hash
end
alias set_imc set_initial_marking_collection
# Creates a new simulation settings collection. If collection identifier is
# not given, resets :Base simulation settings collection to new values.
#
def set_simulation_settings_collection( name=:Base, sim_set_hash )
@simulation_settings_collections[name] = sim_set_hash
end
alias set_ssc set_simulation_settings_collection
# Presents a simulation specified by the argument, which must be a hash with
# four items: :net, :clamp_collection, :inital_marking_collection and
# :simulation_settings_collection.
#
def simulation settings={}
key = case settings
when ~:may_have then # it is a hash or equivalent
settings.may_have :net
settings.may_have :cc, syn!: :clamp_collection
settings.may_have :imc, syn!: :initial_marking_collection
settings.may_have :ssc, syn!: :simulation_settings_collection
{ net: net( settings[:net] || self.Net::Top ), # the key
cc: settings[:cc] || :Base,
imc: settings[:imc] || :Base,
ssc: settings[:ssc] || :Base }
else # use the unprocessed argument itself as the key
settings
end
@simulations[ key ]
end
# Makes a new timed simulation. Named arguments for this method are the same
# as for TimedSimulation#new, but in addition, :name can be supplied.
#
# To create a simulation, simulation settings collection, initial marking
# collection, and clamp collection have to be specified. A place clamp,
# is a fixed value, at which the marking is held. Similarly, initial
# marking is the marking, which a free place receives at the beginning.
# Free places are those, that are not clamped. After initialization, marking
# of free places is allowed to change as the transition fire.
#
# For example, having places :P1..:P5, clamped :P1, :P2 can be written as eg.:
#
# * clamps = { P1: 4, P2: 5 }
#
# Places :P3, :P4, :P5 are free. Their initial marking has to be
# specified, which can be written as eg.:
#
# * initial_markings = { P3: 1, P4: 2, P5: 3 }
#
# As for simulation settings, their exact nature depends on the simulation
# method. For default Euler method, there are 3 important parameters:
# - step_size,
# - sampling_period,
# - target_time
#
# For example, default simulation settings are:
#
# * default_ss = { step_size: 0.1, sampling_period: 5, target_time: 60 }
#
def new_simulation( net: Net().instance( :Top ), **nn )
net_inst = net( net )
nn.may_have :cc, syn!: :clamp_collection
nn.may_have :imc, syn!: :initial_marking_collection
nn.may_have :ssc, syn!: :simulation_settings_collection
cc_id = nn.delete( :cc ) || :Base
imc_id = nn.delete( :imc ) || :Base
ssc_id = nn.delete( :ssc ) || :Base
# Construct the simulation key:
key = if nn.has? :name, syn!: :ɴ then # explicit key (name)
nn[:name]
else # constructed key
{}.merge( net: net_inst,
cc: cc_id,
imc: imc_id,
ssc: ssc_id )
.merge( nn )
end
# Let's clarify what we got so far.
sim_settings = ssc( ssc_id )
mc_hash = cc( cc_id )
im_hash = imc( imc_id )
# Create and return the simulation
sim = net_inst.simulation **sim_settings.merge( initial_marking: im_hash,
marking_clamps: mc_hash
).merge( nn )
@simulations[ key ] = sim
end
end # module YPetri::World::SimulationAspect