ComponentGenerator
With ComponentGenerator components can be generated according to a given inter arrival time (distribution) or a random spread over a given interval.
The bank example as presented in the Modelling chapter can be written as:
1# Bank, 3 clerks (with ComponentGenerator).py
2import salabim as sim
3sim.yieldless(False)
4
5
6
7class Customer(sim.Component):
8 def process(self):
9 self.enter(waitingline)
10 for clerk in clerks:
11 if clerk.ispassive():
12 clerk.activate()
13 break # activate at most one clerk
14 yield self.passivate()
15
16
17class Clerk(sim.Component):
18 def process(self):
19 while True:
20 while len(waitingline) == 0:
21 yield self.passivate()
22 self.customer = waitingline.pop()
23 yield self.hold(30)
24 self.customer.activate()
25
26
27env = sim.Environment(trace=True)
28env.ComponentGenerator(Customer, iat=env.Uniform(5, 15), force_at=True)
29clerks = [Clerk() for _ in range(3)]
30
31waitingline = env.Queue("waitingline")
32
33env.run(till=50000)
34waitingline.print_histograms()
35
36waitingline.print_info()
Examples
sim.ComponentGenerator(Car, iat=sim.Exponential(2))
# generates Cars according to a Poisson arrival
sim.ComponentGenerator(Car, iat=sim.Exponential(2), at=10, till=30, number=10)
# generates maximum 10 Cars according to a Poisson arrival from t=10 to t=30
sim.ComponentGenerator(Car, iat=sim.Exponential(2), at=10, till=30, number=10, force_at=True)
# generates maximum 10 Cars according to a Poisson arrival from t=10 to t=30, first arrival at t=10
sim.ComponentGenerator(sim.Pdf((Car, 0.7, Bus, 0.3)), iat=sim.Uniform(20,40), number=20)
# generates exactly 20 vehicles (70% Car, 30% Bus) according to a uniform inter arrival time
sim.ComponentGenerator(Car, duration=100, number=20)
# generates exactly 20 Cars, random spread over t=now and t=now+100
sim.ComponentGenerator(Car, duration=100, number=20, force_at=True, force_till=True)
# generates exactly 20 Cars, random spread over t=now and t=now+100, with arrivals at t=now and t=now+100
sim.ComponentGenerator(Car, duration=100, number=3, equidistant=True)
# generates exactly 3 Cars, with arrivals at exactly t=now, t=now+50 and t=now+1000
sim.ComponentGenerator(Car, moments=(10,30,90))
# generates exactly 3 Cars, with arrivals at exactly 10, 30 and 90
The chart below illustrates various possibilities.
ComponentGenerator is a subclass of Component and therefore has all the normal properties and methods of an ordinary component, altough it is not recommended to use any of the process methods, apart from cancel.
It is possible to ‘propagate’ parameters to a generated component. This holds for the standard salabim parameters, like name, urgent and priority but also for user class defined parameters.
E.g.
sim.ComponentGenerator(Car, iat=sim.Exponential(2), color='red')
# generates Cars with color=color according to a Poisson arrival
sim.ComponentGenerator(Car, iat=sim.Exponential(2), name='ford.')
# generates Cars according to a Poisson arrival with name ford.0, ford.1
The component_class can also be a callable without paramaters, most like a distribution.
So we can say
sim.ComponentGenerator(sim.Pdf((Car, Bus, Truck), (50, 30, 20)), iat=sim.Exponential(2))
# generates 50% Cars, 30% Buses and 20% Trucks according to a Poisson arrival
It is possible to specify a callback function with the at_end parameter
env.ComponentGenerator(iat=env.Uniform(3,4), number=10, at_end=lambda: env.main().activate())