{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "
\n", " \n", "\n", "\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Clarity with Data: Logistics Decision Making under Risk Part 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simulating Disruption and Predicting Impact: Quantifying Supply Chain Risk Exposure" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In our previous post, we explored the importance of balancing cost and risk in supply chain optimization. We introduced a use case involving a Midwest valve manufacturer facing potential hurricane threats to its coastal suppliers. We walked through the initial steps of building a supply chain model, including defining the scope, bootstrapping the logistics network with OpenStreetMap data, and simulating a basic supplier network. In this post we will continue the example and show how simulation can be used to understand the operational and financial impacts of disruptions on the supply chain. As in previous posts, we will show our work with full implementations in code." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Problem Framing\n", "**Problem**: Natural disasters like hurricanes can significantly disrupt supply chains, leading to delays, production downtimes, and financial losses.\n", "\n", "**Solution**: By simulating the impact of hurricanes on a supply chain network, we can estimate key performance indicators (KPIs) such as delivery delays, production downtimes, and financial losses. This simulation helps in understanding the potential risks and preparing mitigation strategies.\n", "\n", "**Benefit**: Organizations can use these insights to enhance their resilience against natural disasters, minimize disruptions, and reduce financial losses." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simulation Code and Analysis\n", "\n", "The following sections contain the code and analysis for simulating the impact of hurricanes on a supply chain network.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Refactoring Previous Code for Simplicity and Clarity\n", "\n", "To enhance the clarity and maintainability of our code, we've refactored the functionalities from the previous post into reusable libraries. This modular approach not only simplifies the code but also promotes better organization and readability.\n", "\n", "Here's a glimpse of the refactored code:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Import Libraries" ] }, { "cell_type": "code", "execution_count": 107, "metadata": { "tags": [ "hide-input" ] }, "outputs": [], "source": [ "import sys\n", "import os\n", "import json\n", "import logging\n", "import random\n", "import math\n", "import statistics\n", "import networkx as nx\n", "from joblib import Parallel, delayed\n", "from scipy.spatial.distance import euclidean\n", "import numpy as np\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", "from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed\n", "import copy\n", "from matplotlib.ticker import FuncFormatter\n", "\n", "# Enable interactive plots\n", "%matplotlib inline\n", "\n", "# Add the root directory to the Python path\n", "script_dir = os.path.dirname(os.path.abspath(\"__file__\"))\n", "project_root = os.path.abspath(os.path.join(script_dir, \"..\"))\n", "sys.path.append(project_root)\n", "\n", "try:\n", " from supplychain.simulation import build_supply_chain_from_config, simulate_supply_chain\n", " from supplychain.visualization import visualize_supply_chain, assign_supplier_types\n", "except ImportError as e:\n", " logging.error(f\"Error importing modules: {e}\")\n", " raise\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Configure Logging" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "tags": [ "hide-input" ] }, "outputs": [], "source": [ "\n", "# Remove all handlers associated with the root logger object\n", "for handler in logging.root.handlers[:]:\n", " logging.root.removeHandler(handler)\n", "\n", "# Configure logging\n", "logging.basicConfig(\n", " level=logging.ERROR, format=\"%(asctime)s - %(levelname)s - %(message)s\"\n", ")\n", "\n", "logging.info(\"Build supply chain from a configuration file\")\n", "config_filepath = os.path.join(project_root, \"notebooks\", \"sim_config.json\")\n", "combined_graph_filepath = os.path.join(\n", " project_root, \"combined_graph.graphml\"\n", ") # Path to the GraphML file\n", "visualization_filepath = os.path.join(project_root, \"supply_chain_graph.html\")\n", "\n", "# Check if config file exists\n", "if not os.path.exists(config_filepath):\n", " logging.error(f\"Configuration file not found: {config_filepath}\")\n", " sys.exit(1)\n", "\n", "# Load configuration\n", "with open(config_filepath, \"r\") as f:\n", " config = json.load(f)\n", "\n", "G, road_networks = build_supply_chain_from_config(\n", " config_filepath, combined_graph_filepath\n", ")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Create the Supply Chain" ] }, { "cell_type": "code", "execution_count": 124, "metadata": { "tags": [ "hide-input" ] }, "outputs": [ { "data": { "text/html": [ "