Skip to content

Discrete Event Simulatiuon in Python

Discrete Event Simulation in Python

Introduction to Dynamic Systems and Discrete-Event Simulation Models
Dynamic and Steady Systems

Dynamic Systems: Dynamic systems are systems that change over time. These changes can be due to internal factors, external influences, or a combination of both. The state of a dynamic system evolves according to a set of defined rules or equations, which can be deterministic or stochastic. Examples of dynamic systems include weather patterns, stock market fluctuations, and population growth models.

Steady Systems: Steady systems, also known as steady-state systems, are systems that do not change over time. In these systems, the variables remain constant, and there is no evolution or fluctuation in their state. Steady systems are often used as a simplification for analyzing systems where changes are negligible or occur over very long periods. Examples of steady systems include a car moving at a constant speed on a straight road or a chemical reaction that has reached equilibrium.

!pip install simpy
import simpy
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Define the lift discrete event model
def lift_discrete_event_model(sim_time, number_hotel_floors, lift_people_capacity, travel_time_between_floors, stop_time_open_doors):
    # Initialize the simulation environment
    env = simpy.Environment()
    
    # Define the lift process
    def lift(env, number_hotel_floors, lift_people_capacity, travel_time_between_floors, stop_time_open_doors):
        while True:
            for floor in range(number_hotel_floors):
                yield env.timeout(travel_time_between_floors)
                yield env.timeout(stop_time_open_doors)
            for floor in range(number_hotel_floors - 1, -1, -1):
                yield env.timeout(travel_time_between_floors)
                yield env.timeout(stop_time_open_doors)
    
    # Start the lift process
    env.process(lift(env, number_hotel_floors, lift_people_capacity, travel_time_between_floors, stop_time_open_doors))
    
    # Run the simulation
    env.run(until=sim_time)
    
    # Collect results (this is a placeholder, actual implementation may vary)
    results = {
        "Time": np.arange(0, sim_time, 1),
        "Floor": np.random.randint(0, number_hotel_floors, sim_time)
    }
    
    # Convert results to a DataFrame
    df_results = pd.DataFrame(results)
    
    return df_results

# Create a dictionary containing the processes and durations
processes = {
    "Sourcing": 5,
    "Manufacturing": 3,
    "Assembling": 2,
    "Selling": 3,
    "Delivering": 4
}

# Floor and lift parameters
number_hotel_floors = 5
lift_people_capacity = 15
travel_time_between_floors = 0.05
stop_time_open_doors = 0.1
sim_time = 5

# Run the model
df_results = lift_discrete_event_model(sim_time, number_hotel_floors, lift_people_capacity, travel_time_between_floors, stop_time_open_doors)

# Display the results
df_results
Mathematical models of dynamic systems
Defining a Mathematical Model

A mathematical model is a description of a system using mathematical concepts and language. The process of developing a mathematical model is termed 'mathematical modeling'. Mathematical models are used in the natural sciences (such as physics, biology, earth science, meteorology) and engineering disciplines (such as computer science, artificial intelligence), as well as in the social sciences (such as economics, psychology, sociology, political science).

A mathematical model can take many forms, including but not limited to:

  • Differential Equations: Used to describe the behavior of dynamic systems.
  • Algebraic Equations: Used for systems in equilibrium.
  • Statistical Models: Used to represent data and infer relationships.
  • Stochastic Models: Incorporate randomness and are used for systems that are inherently unpredictable.

The choice of model depends on the nature of the system being studied and the goals of the analysis. For example, in the context of dynamic systems, differential equations are often used to model the change in system states over time.

Here is a simple example of a differential equation used to model the growth of a population:

[ \frac{dP}{dt} = rP ]

where:

  • ( P ) is the population size,
  • ( t ) is time,
  • ( r ) is the growth rate.

This equation states that the rate of change of the population over time is proportional to the current population size, which is a characteristic of exponential growth.

import matplotlib.pyplot as plt

# Model engine

def discrete_model(processes, simulation_time):
    # Initialize time
    time = 0
    time_series = [time]
    
    # Run end condition
    while (time < simulation_time):
        process_names = list(processes.keys())
        
        # Loop over all processes
        for p in range(len(process_names)):
            process_name_p = process_names[p]
            
            # account for effect of each process
            time += processes[process_name_p]
            time_series.append(time)
    
    return time_series

# Run configuration

# Simulation period
simulation_time = 365

# Define processes (example)
processes = {
    'process_1': 5,
    'process_2': 2,
    'process_3': 3
}

# Run model
time_series = discrete_model(processes, simulation_time)

# Generate x and y data for plotting
x = range(len(time_series))
y = time_series

plt.plot(x, y, color='green', marker='o',
        markersize=2, linestyle='dashed',
        linewidth=2)
plt.xlabel('Step')
plt.ylabel('Time')
plt.title('Discrete Model Simulation')
plt.show()
# Exercises

processes = {
    "Sourcing raw material":  5,
    "Transport of raw material": 1,
    "Manufacturing parts": 3,
    "Assembling parts": 2,
    "Selling products": 3,
}

# Add the new key-value pair to the processes dictionary
processes["Delivering products"] = 1.5

# Assign the simulation time
simulation_time = 365*5

# Define the discrete_model_build_phone function
def discrete_model_build_phone(processes, simulation_time):
    cumulative_time = []
    individual_process_time = []
    total_time = 0
    for process, duration in processes.items():
        total_time += duration
        cumulative_time.append(total_time)
        individual_process_time.append(duration)
    return cumulative_time, individual_process_time

# Run the model
time_all = discrete_model_build_phone(processes, simulation_time)

cumulative_time = time_all[0]
individual_process_time = time_all[1]

# Create 2D plot
import matplotlib.pyplot as plt

plt.plot(cumulative_time, individual_process_time,
         color='black', markerfacecolor='mediumvioletred',
         marker='o', markersize=6, linewidth=1.5)

plt.xlabel("Cumulative duration (days)")
plt.ylabel("Duration of each process (days)")
plt.grid()
plt.show()
Introduction to discrete event simulations

Discrete Event Models

Discrete event models are a type of simulation where the operation of a system is represented as a chronological sequence of events. Each event occurs at a specific instant in time and marks a change of state in the system. These models are particularly useful for systems where changes occur at discrete points in time, rather than continuously.

Key Concepts
  1. Events: The fundamental units of change in the system. Each event occurs at a specific time and triggers a change in the state of the system.
  2. State: The collection of variables that describe the system at any given time.
  3. Clock: A variable that keeps track of the current simulation time.
  4. Event List: A list that keeps track of all scheduled events and their associated times.
Applications
  • Manufacturing processes
  • Queueing systems
  • Computer networks
  • Traffic flow
Example

In the provided code, a discrete event model is used to simulate the process of building a phone. The model tracks the cumulative time and individual process times for various stages such as sourcing raw material, manufacturing parts, and delivering products.

# Define the discrete_model_build_phone function def discrete_model_build_phone(processes, simulation_time): cumulative_time = [] individual_process_time = [] total_time = 0 for process, duration in processes.items(): total_time += duration cumulative_time.append(total_time) individual_process_time.append(duration) return cumulative_time, individual_process_time # Run the model time_all = discrete_model_build_phone(processes, simulation_time) cumulative_time = time_all[0] individual_process_time = time_all[1] # Create 2D plot import matplotlib.pyplot as plt plt.plot(cumulative_time, individual_process_time, color='black', markerfacecolor='mediumvioletred', marker='o', markersize=6, linewidth=1.5) plt.xlabel("Cumulative duration (days)") plt.ylabel("Duration of each process (days)") plt.grid() plt.show()
# Mock functions to simulate the behavior of manage_requests and dispatch_taxi
import random

def manage_requests():
    return random.randint(1, 3)

def dispatch_taxi():
    return random.randint(1, 3)

# Initialize time
time = 0

# Model components
while time < 10:
    # Process 1
    time_duration_1 = manage_requests()
    time += time_duration_1
    
    # Process 2
    time_duration_2 = dispatch_taxi()
    time += time_duration_2

    # Output the current time for debugging purposes
    print(f"Current time: {time}")
Hidden output
# Exercises

def discrete_model_farm(process_dict, simulation_time):
  # Initiate variables
  time = 0
  supply_chain = 0

  # Define ending condition
  while time < simulation_time:

    supply_chain += 1
    process_names = list(process_dict.keys())

    for p in range(len(process_names)):
		  
      event_duration = process_dict[process_names[p]]
          
      # Add the process duration
      time += event_duration
      print(f"{process_names[p]}  (completed): time = {time}")
          
    print(f"COMPLETED: Production cycle #{supply_chain} | Time = {time} days")  
    
# Create dictionary
process_dict = {
    "Compost": 5,
    "Amendment": 3,
    "Weeding": 4,
    "Planting": 2,
    "Watering and growing": 60,
    "Harvesting": 7,
    "Delivery": 2
}

# Simulatiom time (days)
simulation_time = 365

# Run the model
discrete_model_farm(process_dict, simulation_time)
Hidden output