# Variable Number of Servers¶

In this example we will consider a network where servers are added and removed depending on the system state. We will look at a system without this behaviour first, and then the system with the desired behaviour, for comparison.

## Without desired behaviour¶

Consider an M/M/1 queue with $$\Lambda = 1$$ and $$\mu = 0.4$$. Here the traffic intensity of the system is greater than one, that is we have customers arriving faster than can be served, and so the queue size will increase over time. Let’s see this:

>>> import ciw

>>> N = ciw.create_network(
...     arrival_distributions=[ciw.dists.Exponential(rate=1)],
...     service_distributions=[ciw.dists.Exponential(rate=0.4)],
...     number_of_servers=[1]
... )

>>> ciw.seed(0)
>>> Q = ciw.Simulation(N, tracker=ciw.trackers.SystemPopulation())
>>> Q.simulate_until_max_time(100)


Now let’s plot the system population over time:

>>> plt.plot(
...     [row[0] for row in Q.statetracker.history],
...     [row[1] for row in Q.statetracker.history]
... );


## With desired behaviour¶

We will now create a AdaptiveNode that will add two servers if the population exceeds 10 individuals, and then drop back down to one server if the population drops back down to 3 individuals. First create the AdaptiveNode that inherits from the ciw.Node class, and overwrite the have_event methods so it first checks the population size and adds / removes servers as needed:

>>> class AdaptiveNode(ciw.Node):
...     def have_event(self):
...         if (len(self.all_individuals) > 10) and (len(self.servers) == 1):
...         elif (len(self.all_individuals) < 4) and (len([s for s in self.servers if not s.offduty]) == 3):
...             print(f'Removing servers at {self.now:.3f}')
...             self.take_servers_off_duty()
...         super().have_event()


Here print statements have also been added to record when the changes in the numbers of servers occur.

Now rerun the same system, telling Ciw to use the new node_class. We’ll still begin with just one server:

>>> ciw.seed(0)
>>> Q = ciw.Simulation(N, node_class=AdaptiveNode, tracker=ciw.trackers.SystemPopulation())
>>> Q.simulate_until_max_time(100)

>>> plt.plot(