Skip to content

4 Input Variables

becauselol edited this page Dec 13, 2023 · 1 revision

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

Passenger Arrivals

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.

Arrival Patterns

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:

  1. Uniform Arrival Pattern
  2. 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.

Uniform Arrival Pattern

  • 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 $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{6}$
2 $\frac{1}{30}$ 0 $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{6}$
3 $\frac{1}{30}$ $\frac{1}{30}$ 0 $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{6}$
4 $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ 0 $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{6}$
5 $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ 0 $\frac{1}{30}$ $\frac{1}{6}$
6 $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ $\frac{1}{30}$ 0 $\frac{1}{6}$
Total $\frac{1}{6}$ $\frac{1}{6}$ $\frac{1}{6}$ $\frac{1}{6}$ $\frac{1}{6}$ $\frac{1}{6}$

Ground Floor Heavy Pattern

  • 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 $0.35$

1 2 3 4 5 6 Total
1 0 $0.07$ $0.07$ $0.07$ $0.07$ $0.07$ $0.35$
2 $0.07$ 0 $0.015$ $0.015$ $0.015$ $0.015$ $0.13$
3 $0.07$ $0.015$ 0 $0.015$ $0.015$ $0.015$ $0.13$
4 $0.07$ $0.015$ $0.015$ 0 $0.015$ $0.015$ $0.13$
5 $0.07$ $0.015$ $0.015$ $0.015$ 0 $0.015$ $0.13$
6 $0.07$ $0.015$ $0.015$ $0.015$ $0.015$ 0 $0.13$
Total $0.35$ $0.13$ $0.13$ $0.13$ $0.13$ $0.13$

Group Control Strategy

For Group Control Strategy, we chose to adopt and test 3 strategies.

  1. Random Assignment
    • This is our control strategy
  2. Zoning Assignment
    • External calls from each floor are assigned to specific elevators
  3. 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.

Random Assignment

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.

Zoning Assignment

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])

Nearest Elevator Assignment

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:

  1. The Elevator is moving towards the floor_call in the same direction
    • heuristic = abs(elevator.floor - floor_call)
  2. The Elevator is moving away from the floor_call in the same direction
    • heuristic = 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
  3. The Elevator is moving away from the floor_call in the opposite direction
    • heuristic = 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
  4. The Elevator is moving towards the floor_call in the opposite direction
    • heuristic = 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 heuristic

Idle Floor Configuration

The 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.

Clone this wiki locally