| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- ### DO NOT EDIT THIS FILE ###
- from pypdevs.DEVS import AtomicDEVS
- import random
- import dataclasses
- # The reason for annotating the *State-classes as 'dataclass', is because this automatically generates a nice __repr__-function, so that if the simulator is set to verbose, you can actually see what the state is.
- class Ship:
- def __init__(self, size, creation_time):
- self.size = size
- self.creation_time = creation_time
- # useful in verbose mode:
- def __repr__(self):
- return f"Ship(size={self.size},created={self.creation_time})"
- @dataclasses.dataclass
- class GeneratorState:
- current_time: float
- time_until_next_ship: float
- to_generate: int
- random: random.Random
- def __init__(self, seed=0, gen_num=1000):
- self.current_time = 0.0 # for statistics only
- self.time_until_next_ship = 0.0
- self.to_generate = gen_num
- self.random = random.Random(seed)
- class Generator(AtomicDEVS):
- def __init__(self,
- seed=0, # random seed
- lambd=1.0/60.0, # how often to generate a ship - in this example, once per minute
- gen_types=[1,1,2], # ship sizes to generate, will be sampled uniformly - in this example, size 1 is twice as likely as size 2.
- gen_num=1000, # number of ships total to generate
- ):
- super().__init__("Generator")
- # State (for everything that is mutable)
- self.state = GeneratorState(seed=seed, gen_num=gen_num)
- # I/O
- self.out_ship = self.addOutPort("out_event")
- # Parameters (read-only)
- self.lambd = lambd
- self.gen_types = gen_types
- def timeAdvance(self):
- return self.state.time_until_next_ship
- def outputFnc(self):
- size = self.state.random.choice(self.gen_types) # uniformly sample from gen_types
- # watch out: outputFnc is called *before* intTransition!
- creation = self.state.current_time + self.state.time_until_next_ship
- return { self.out_ship: Ship(size, creation) }
- def intTransition(self):
- self.state.current_time += self.state.time_until_next_ship
- self.state.to_generate -= 1
- if self.state.to_generate > 0:
- self.state.time_until_next_ship = self.state.random.expovariate(self.lambd)
- else:
- # stop generating
- self.state.time_until_next_ship = float('inf')
- return self.state
- @dataclasses.dataclass
- class SinkState:
- current_time: float
- ships: list
- def __init__(self):
- self.current_time = 0.0
- self.ships = []
- class Sink(AtomicDEVS):
- def __init__(self):
- super().__init__("Sink")
- self.state = SinkState()
- self.in_ships = self.addInPort("in_ships")
- def extTransition(self, inputs):
- self.state.current_time += self.elapsed
- if self.in_ships in inputs:
- ships = inputs[self.in_ships]
- for ship in ships:
- ship.finished_time = self.state.current_time
- # amount of time spent in the system:
- ship.queueing_duration = ship.finished_time - ship.creation_time
- self.state.ships.extend(ships)
- return self.state
- ### DO NOT EDIT THIS FILE ###
|