-
Notifications
You must be signed in to change notification settings - Fork 0
4 Input Variables
Within the simulation, we are able to then modify various inputs to experiment with and find out how we can minimize our objectives with respect to various conditions
All passenger arrivals are modelled as a Poisson process and the overall arrival rate of passengers can be set in the simulation.
The probabilities of spawning the different profiles of passengers (source and destination of each passenger) is defined as in the below section.
Elevator Control Systems need to be able to handle different kinds of arrival patterns.
Depending on the arrival pattern of customers, a group control system needs to adapt their parameters to achieve the same operational success.
While there are many types of arrival patterns, our project will focus on two as defined by our assumptions:
- Uniform Arrival Pattern
- Ground Floor Heavy Arrival Pattern
For the simulation, we can also define a overall total_arrival_rate that determines the total amount of passengers that arrive into the system. The probabilities then split the people up equally over the required movements in the building.
- Assumes that an equal amount of people arrive at every floor
- Equal proportion of people want to go from one floor to every other floor
An example of arrival probabilities from each floor to every other floor is as shown below:
| 1 | 2 | 3 | 4 | 5 | 6 | Total | |
|---|---|---|---|---|---|---|---|
| 1 | 0 | ||||||
| 2 | 0 | ||||||
| 3 | 0 | ||||||
| 4 | 0 | ||||||
| 5 | 0 | ||||||
| 6 | 0 | ||||||
| Total |
- A fixed proportion of people arriving and leaving every floor
- An equal proportion of people go from ground floor to every other floor
- Same proportion of people going from ground to other floors is same as proportion going from other floors to ground
- Remaining proportion of people going between the remaining floors are split equally
In this example, we fix the fixed proportion of people arriving and leaving level 1 as
| 1 | 2 | 3 | 4 | 5 | 6 | Total | |
|---|---|---|---|---|---|---|---|
| 1 | 0 | ||||||
| 2 | 0 | ||||||
| 3 | 0 | ||||||
| 4 | 0 | ||||||
| 5 | 0 | ||||||
| 6 | 0 | ||||||
| Total |
For Group Control Strategy, we chose to adopt and test 3 strategies.
- Random Assignment
- This is our control strategy
- Zoning Assignment
- External calls from each floor are assigned to specific elevators
- Nearest Elevator Assignment
- External calls are assigned based on a heuristic based on the floor the elevators are on
Each Group Controller only has differences in their implementation of the method assign_call.
Details on each assignment strategy and the respective code is shown below.
For random assignment, the assign_call method is simply as follows
def assign_call(self, floor_call, direction, time):
return random.randint(1, self.num_elevators)This just means that a random elevator is assigned anytime a new external call is made.
For zoning assignment, we first assigned each elevator to a set of floors. For the purpose of our simulation, the following is the zoning configuration
zones = {
1: [1, 2],
2: [3, 4],
3: [5, 6]
}This means that:
- Elevator 1 will only respond to calls from Floor 1 and 2
- Elevator 2 will only respond to calls from Floor 3 and 4
- Elevator 3 will only respond to calls from Floor 5 and 6
Each floor is then mapped to the elevators in a dictionary floor_to_elevator. This way, if there are multiple elevators assigned to the same floor, the simulation can still handle it. However, if multiple elevators are assigned to the same floor, when a call is made, the call will randomly be assigned to the assigned elevators.
Then the assign_call method is as follows:
def assign_call(self, floor_call, direction, time):
return random.choice(self.floor_to_elevator[floor_call])For the Nearest Elevator Assignment method, we calculate the assumed worst case distance that the elevator will travel as a heuristic. Hence, whichever elevator is the closest in terms of this heuristic will be assigned to respond to the external call.
This meant that the assign_call function simply calculates the heuristic value for each elevator and based on the minimum values, find the elevators that fulfil this condition and select an elevator that has the lowest heuristic value.
def assign_call(self, floor_call, direction, time):
heuristic_values = [(self.heuristic(elevator_id, floor_call, direction), elevator_id) for elevator_id in range(1, self.num_elevators + 1)]
min_val, _ = min(heuristic_values)
min_choices = [e_id for h, e_id in heuristic_values if h == min_val]
return random.choice(min_choices)The heuristic is calculated as based on the following cases:
- The Elevator is moving towards the
floor_callin the samedirectionheuristic = abs(elevator.floor - floor_call)
- The Elevator is moving away from the
floor_callin the samedirectionheuristic = 2 * self.num_floors - abs(elevator.floor - floor_call)- This is because based on the SCAN algorithm, the elevator will at most move to the highest/lowest floor, then back to the lowest/highest floor and then finally to the
floor_call
- The Elevator is moving away from the
floor_callin the oppositedirectionheuristic = 2 * elevator.floor + abs(elevator.floor - floor_call)- This is because based on the SCAN algorithm, the elevator will at most move to the highest/lowest floor, then back to the
floor_call
- The Elevator is moving towards the
floor_callin the oppositedirectionheuristic = 2 * floor_call + abs(elevator.floor - floor_call)- This is because based on the SCAN algorithm, the elevator will at most move to the highest/lowest floor, then back to the
floor_call
This heuristic calculation is as shown in the method heuristic
def heuristic(self, elevator_id, floor_call, direction):
elevator = self.liftControllers[elevator_id].elevator
heuristic = abs(elevator.floor - floor_call)
if direction == elevator.direction:
if elevator.floor * direction.value >= floor_call * direction.value:
heuristic = 2 * self.num_floors - heuristic
else:
if elevator.direction in [Move.UP, Move.DOWN]:
if elevator.floor * direction.value >= floor_call * direction.value:
heuristic = 2 * floor_call + heuristic
else:
heuristic = 2 * elevator.floor + heuristic
return heuristicThe Idle Floor for each elevator can also be configured.
The Idle Floor determines the floor that an elevator returns to after it no longer has any calls to respond to.
Given that this can be configured for each lift, this means that there is a variety of configurations that we can set the 3 lifts to. There are a total of 56 combinations to test.
This is because there are duplicated configurations, which thus reduce the number of unique combinations to only 56. For example the settings [1, 2, 3] is the same as [1, 3, 2]. Hence, there are only 56 unique combinations.
The Idle Floor Configurations are important to explore as it would reduce the distance taken for the elevators to travel from their idle state to the external calls.