Introduction
In this tutorial, you'll learn how to create a simple simulation of a supply chain disruption using Python. Based on recent news about Iran's impact on the AI supply chain, particularly the disruption of epoxy resin production for PCBs, we'll build a model that demonstrates how a single disruption can ripple through the entire system. This simulation will help you understand the interconnected nature of modern supply chains and how a problem in one component can affect multiple downstream systems.
Prerequisites
- Basic understanding of Python programming concepts
- Python 3.x installed on your computer
- Optional: A code editor like VS Code or Jupyter Notebook
Step-by-Step Instructions
1. Setting Up Your Python Environment
1.1 Create a new Python file
Start by creating a new file called supply_chain_simulation.py. This will be our main simulation file.
1.2 Import necessary libraries
At the top of your file, add the following imports:
import random
import time
from datetime import datetime, timedelta
Why we do this: We need these libraries to generate random data, handle time calculations, and simulate realistic supply chain behavior.
2. Creating the Supply Chain Components
2.1 Define a basic component class
Let's create a base class for all supply chain components:
class SupplyChainComponent:
def __init__(self, name, lead_time_days=7):
self.name = name
self.lead_time_days = lead_time_days
self.stock_level = 1000
self.is_operational = True
def __str__(self):
return f"{self.name} (Stock: {self.stock_level}, Operational: {self.is_operational})"
def consume_stock(self, amount):
if self.stock_level >= amount:
self.stock_level -= amount
return True
return False
def add_stock(self, amount):
self.stock_level += amount
Why we do this: This class represents any component in our supply chain - from raw materials to finished products. It tracks stock levels and operational status.
2.2 Create specific components
Now let's create specific components that represent our supply chain:
class EpoxyResin(SupplyChainComponent):
def __init__(self):
super().__init__("Epoxy Resin", lead_time_days=14)
def disrupt_supply(self):
self.is_operational = False
print(f"🚨 {self.name} supply has been disrupted!")
def restore_supply(self):
self.is_operational = True
print(f"✅ {self.name} supply has been restored!")
class PCB(LayeredComponent):
def __init__(self):
super().__init__("PCB", lead_time_days=7)
self.resin_needed = 50
def produce(self):
if self.consume_stock(self.resin_needed):
print(f"✅ {self.name} produced successfully")
return True
else:
print(f"❌ Not enough resin to produce {self.name}")
return False
class ElectronicsManufacturer(SupplyChainComponent):
def __init__(self, name):
super().__init__(name, lead_time_days=10)
self.pcb_needed = 100
def produce_product(self):
if self.consume_stock(self.pcb_needed):
print(f"✅ {self.name} produced successfully")
return True
else:
print(f"❌ Not enough PCBs to produce {self.name}")
return False
Why we do this: We're creating specific components that represent different parts of the supply chain. The epoxy resin is the disrupted component, PCBs are the intermediate product, and electronics manufacturers are the end users.
3. Building the Simulation Logic
3.1 Create the simulation manager
class SupplyChainSimulator:
def __init__(self):
self.components = []
self.disruption_time = None
def add_component(self, component):
self.components.append(component)
def simulate_normal_operation(self, days=5):
print("\n=== Normal Supply Chain Operation ===")
for day in range(days):
print(f"\nDay {day + 1}:")
for component in self.components:
if hasattr(component, 'produce') and component.is_operational:
component.produce()
elif component.is_operational:
print(f" {component.name} is operational")
time.sleep(0.5) # Pause for visualization
def simulate_disruption(self, disruption_duration_days=3):
print("\n=== Supply Chain Disruption ===")
# Find and disrupt epoxy resin
epoxy = next((c for c in self.components if isinstance(c, EpoxyResin)), None)
if epoxy:
epoxy.disrupt_supply()
self.disruption_time = datetime.now()
# Show how disruption affects downstream components
for day in range(disruption_duration_days):
print(f"\nDay {day + 1} (Disruption Day {day + 1}):")
for component in self.components:
if isinstance(component, EpoxyResin):
print(f" {component.name}: Disrupted")
elif isinstance(component, PCB):
component.produce() # This will fail due to lack of resin
elif isinstance(component, ElectronicsManufacturer):
component.produce_product() # This will fail due to lack of PCBs
time.sleep(0.5)
def simulate_recovery(self, recovery_days=3):
print("\n=== Supply Chain Recovery ===")
# Restore epoxy resin
epoxy = next((c for c in self.components if isinstance(c, EpoxyResin)), None)
if epoxy:
epoxy.restore_supply()
# Show recovery process
for day in range(recovery_days):
print(f"\nDay {day + 1} (Recovery Day {day + 1}):")
for component in self.components:
if isinstance(component, EpoxyResin):
print(f" {component.name}: Restoring supply")
elif isinstance(component, PCB):
component.produce() # This should now work
elif isinstance(component, ElectronicsManufacturer):
component.produce_product() # This should now work
time.sleep(0.5)
Why we do this: This class manages our entire simulation, allowing us to run normal operations, simulate disruptions, and show recovery phases.
3.2 Initialize and run the simulation
def main():
# Create simulator
simulator = SupplyChainSimulator()
# Create components
epoxy = EpoxyResin()
pcb = PCB()
manufacturer1 = ElectronicsManufacturer("Samsung")
manufacturer2 = ElectronicsManufacturer("AMD")
# Add components to simulator
simulator.add_component(epoxy)
simulator.add_component(pcb)
simulator.add_component(manufacturer1)
simulator.add_component(manufacturer2)
# Run simulation
simulator.simulate_normal_operation(3)
simulator.simulate_disruption(3)
simulator.simulate_recovery(3)
print("\n=== Simulation Complete ===")
if __name__ == "__main__":
main()
Why we do this: This is the main function that ties everything together. It creates our supply chain components, runs the simulation, and shows how disruptions propagate through the system.
4. Running the Simulation
4.1 Execute the code
Save your file and run it using Python:
python supply_chain_simulation.py
Why we do this: Running the code will execute our simulation and show how disruptions affect the supply chain step by step.
4.2 Analyze the output
When you run the simulation, you'll see output like:
=== Normal Supply Chain Operation ===
Day 1:
PCB produced successfully
Samsung produced successfully
AMD produced successfully
Day 2:
PCB produced successfully
Samsung produced successfully
AMD produced successfully
=== Supply Chain Disruption ===
Day 1 (Disruption Day 1):
Epoxy Resin: Disrupted
PCB: Not enough resin to produce PCB
Samsung: Not enough PCBs to produce Samsung
AMD: Not enough PCBs to produce AMD
Why we do this: The output shows how a disruption in one component (epoxy resin) immediately affects downstream components (PCBs, then electronics manufacturers).
5. Enhancing the Simulation
5.1 Add more realistic delays
Enhance your simulation by adding realistic delays and more complex interactions:
class AdvancedSupplyChainSimulator(SupplyChainSimulator):
def __init__(self):
super().__init__()
self.disruption_start_time = None
def calculate_delay(self, base_delay, disruption_multiplier=1.0):
# Add random variation to delays
variation = random.uniform(0.5, 1.5)
return int(base_delay * variation * disruption_multiplier)
def simulate_disruption_with_delay(self, disruption_duration_days=3):
print("\n=== Advanced Disruption Simulation ===")
epoxy = next((c for c in self.components if isinstance(c, EpoxyResin)), None)
if epoxy:
epoxy.disrupt_supply()
self.disruption_start_time = datetime.now()
# Simulate delayed impact
for day in range(disruption_duration_days):
print(f"\nDay {day + 1}:")
# Delayed effect on downstream components
if day >= 1: # After one day of disruption
for component in self.components:
if isinstance(component, PCB):
component.produce()
elif isinstance(component, ElectronicsManufacturer):
component.produce_product()
else:
print(" No immediate effect")
time.sleep(1)
Why we do this: This enhancement makes our simulation more realistic by adding random delays and showing how disruptions don't have immediate effects but propagate over time.
Summary
In this tutorial, you've learned how to create a basic supply chain simulation that demonstrates how disruptions in one part of the system can affect the entire supply chain. You've built a model that simulates the impact of Iran's disruption to epoxy resin production on downstream components like PCB manufacturing and electronics manufacturers.
This simple simulation helps illustrate why supply chain disruptions are so critical - even a single point of failure can cause cascading effects throughout an entire industry. The code you've written can be extended to include more components, more complex relationships, and additional disruption scenarios to better model real-world supply chain challenges.



