# 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
```

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())
```