[go: up one dir, main page]

0% found this document useful (0 votes)
23 views14 pages

Code Nhóm 1 FGDFG

The document outlines a process for airline planning following flight disruptions, utilizing data analysis with Python libraries such as pandas and networkx. It includes loading flight rotation data, analyzing flight and aircraft information, and visualizing flight networks among selected airports. The document also details the creation of directed graphs to represent flight connections and the calculation of costs and passenger numbers for flight itineraries.

Uploaded by

dl4766721
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views14 pages

Code Nhóm 1 FGDFG

The document outlines a process for airline planning following flight disruptions, utilizing data analysis with Python libraries such as pandas and networkx. It includes loading flight rotation data, analyzing flight and aircraft information, and visualizing flight networks among selected airports. The document also details the creation of directed graphs to represent flight connections and the calculation of costs and passenger numbers for flight itineraries.

Uploaded by

dl4766721
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Airline planning after flight disruption

%pip install networkx matplotlib seaborn


import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")
from datetime import datetime, timedelta
import random
import csv
import plotly.express as px

Requirement already satisfied: networkx in


/usr/local/lib/python3.11/dist-packages (3.5)
Requirement already satisfied: matplotlib in
/usr/local/lib/python3.11/dist-packages (3.10.0)
Requirement already satisfied: seaborn in
/usr/local/lib/python3.11/dist-packages (0.13.2)
Requirement already satisfied: contourpy>=1.0.1 in
/usr/local/lib/python3.11/dist-packages (from matplotlib) (1.3.2)
Requirement already satisfied: cycler>=0.10 in
/usr/local/lib/python3.11/dist-packages (from matplotlib) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in
/usr/local/lib/python3.11/dist-packages (from matplotlib) (4.58.4)
Requirement already satisfied: kiwisolver>=1.3.1 in
/usr/local/lib/python3.11/dist-packages (from matplotlib) (1.4.8)
Requirement already satisfied: numpy>=1.23 in
/usr/local/lib/python3.11/dist-packages (from matplotlib) (2.0.2)
Requirement already satisfied: packaging>=20.0 in
/usr/local/lib/python3.11/dist-packages (from matplotlib) (24.2)
Requirement already satisfied: pillow>=8 in
/usr/local/lib/python3.11/dist-packages (from matplotlib) (11.2.1)
Requirement already satisfied: pyparsing>=2.3.1 in
/usr/local/lib/python3.11/dist-packages (from matplotlib) (3.2.3)
Requirement already satisfied: python-dateutil>=2.7 in
/usr/local/lib/python3.11/dist-packages (from matplotlib)
(2.9.0.post0)
Requirement already satisfied: pandas>=1.2 in
/usr/local/lib/python3.11/dist-packages (from seaborn) (2.2.2)
Requirement already satisfied: pytz>=2020.1 in
/usr/local/lib/python3.11/dist-packages (from pandas>=1.2->seaborn)
(2025.2)
Requirement already satisfied: tzdata>=2022.7 in
/usr/local/lib/python3.11/dist-packages (from pandas>=1.2->seaborn)
(2025.2)
Requirement already satisfied: six>=1.5 in
/usr/local/lib/python3.11/dist-packages (from python-dateutil>=2.7-
>matplotlib) (1.17.0)

df_current_plan =
pd.read_csv('https://raw.githubusercontent.com/Gurobi/modeling-
examples/master/aviation_planning/data/flight_rotations_2006-07-
01.csv')
# if you run this notebook locally, you can also use
#df_current_plan = pd.read_csv('data/flight_rotations_2006-07-01.csv')

df_current_plan['start_time'] =
pd.to_datetime(df_current_plan['start_time'], format='%H:%M')
df_current_plan['start_time'] = df_current_plan['start_time'].dt.time
df_current_plan['end_time'] =
pd.to_datetime(df_current_plan['end_time'], format='%H:%M')
df_current_plan['end_time'] = df_current_plan['end_time'].dt.time
df_current_plan['duration'] =
pd.to_datetime(df_current_plan['duration'], format='%H:%M')
df_current_plan['duration'] = df_current_plan['duration'].dt.time
df_current_plan

{"summary":"{\n \"name\": \"df_current_plan\",\n \"rows\": 608,\n


\"fields\": [\n {\n \"column\": \"flight\",\n
\"properties\": {\n \"dtype\": \"number\",\n \"std\":
1790,\n \"min\": 1,\n \"max\": 5166,\n
\"num_unique_values\": 608,\n \"samples\": [\n 2610,\n
6,\n 4359\n ],\n \"semantic_type\": \"\",\n
\"description\": \"\"\n }\n },\n {\n \"column\":
\"date\",\n \"properties\": {\n \"dtype\": \"object\",\n
\"num_unique_values\": 1,\n \"samples\": [\n
\"7/1/06\"\n ],\n \"semantic_type\": \"\",\n
\"description\": \"\"\n }\n },\n {\n \"column\":
\"aircraft\",\n \"properties\": {\n \"dtype\":
\"category\",\n \"num_unique_values\": 85,\n
\"samples\": [\n \"ERJ135#1\"\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"ori\",\n \"properties\": {\n
\"dtype\": \"category\",\n \"num_unique_values\": 35,\n
\"samples\": [\n \"BIA\"\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"des\",\n \"properties\": {\n
\"dtype\": \"category\",\n \"num_unique_values\": 35,\n
\"samples\": [\n \"LIG\"\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"start_time\",\n
\"properties\": {\n \"dtype\": \"category\",\n
\"num_unique_values\": 194,\n \"samples\": [\n
\"16:15:00\"\n ],\n \"semantic_type\": \"\",\n
\"description\": \"\"\n }\n },\n {\n \"column\":
\"end_time\",\n \"properties\": {\n \"dtype\":
\"category\",\n \"num_unique_values\": 196,\n
\"samples\": [\n \"17:20:00\"\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"duration\",\n \"properties\":
{\n \"dtype\": \"category\",\n \"num_unique_values\":
20,\n \"samples\": [\n \"00:30:00\"\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n }\n ]\n}","type":"dataframe","variable_name":"df_current_plan"}

flights = df_current_plan['flight'].unique()
aircrafts = df_current_plan['aircraft'].unique()
airports = set(df_current_plan['ori'].unique()
+df_current_plan['des'].unique())

print(len(flights),"flights between",len(airports),"airports operated


with",len(aircrafts),"aircrafts")

608 flights between 35 airports operated with 85 aircrafts

from IPython.display import Image, display


import networkx as nx
from networkx.drawing.nx_agraph import graphviz_layout
from networkx.drawing.nx_agraph import to_agraph

arcs = list(df_current_plan[['ori','des']].itertuples(index=False,
name=None)) # store the origin-destination pairs of all the flights

n_airports = 4 # specify how many airports to pick

G = nx.MultiDiGraph() # create an empty directed graph


G.add_edges_from(arcs) # add the origin-destination pairs to the graph
as directed edges

top_airports = [i for (i,j) in sorted(G.degree, key=lambda x: x[1],


reverse=True)[:n_airports]] # pre-select top airports by their degree

G = G.subgraph(top_airports) # reduce the graph to just the top few


airports

# reduce the current plan dataframe to just the top few airports
df_current_plan =
df_current_plan[df_current_plan['ori'].isin(top_airports)]
df_current_plan =
df_current_plan[df_current_plan['des'].isin(top_airports)]

# # visualize the network


# A_graph = to_agraph(G)
# A_graph.layout('dot')
# display(A_graph)
flights = df_current_plan['flight'].unique()
aircrafts = df_current_plan['aircraft'].unique()
airports = set(df_current_plan['ori'].unique()
+df_current_plan['des'].unique())

print("The reduced data has",len(flights),"flights


between",len(airports),"airports operated
with",len(aircrafts),"aircrafts")

The reduced data has 222 flights between 4 airports operated with 21
aircrafts

flight_origin = df_current_plan.set_index('flight')['ori'].to_dict()
flight_dest = df_current_plan.set_index('flight')['des'].to_dict()
flight_start_time = df_current_plan.set_index('flight')
['start_time'].to_dict()
flight_end_time = df_current_plan.set_index('flight')
['end_time'].to_dict()

df_starting_positions =
pd.read_csv('https://raw.githubusercontent.com/Gurobi/modeling-
examples/master/aviation_planning/data/starting_positions.csv')
# if you run this notebook locally, you can also use
#df_starting_positions = pd.read_csv('data/starting_positions.csv')
aircrafts_startpositions_airc =
df_starting_positions.set_index('aircraft')['airport'].to_dict()

df_ending_positions =
pd.read_csv('https://raw.githubusercontent.com/Gurobi/modeling-
examples/master/aviation_planning/data/ending_positions.csv')
# if you run this notebook locally, you can also use
#df_ending_positions = pd.read_csv('data/ending_positions.csv')
aircrafts_endpositions_airc =
df_ending_positions.set_index('aircraft')['airport'].to_dict()

df_iterinaries =
pd.read_csv('https://raw.githubusercontent.com/Gurobi/modeling-
examples/master/aviation_planning/data/flight_iterinaries.csv')
#df_iterinaries = pd.read_csv('data/flight_iterinaries.csv')
df_iterinaries['total_cost'] =
df_iterinaries['cost']*df_iterinaries['n_pass']
flight_revenue = df_iterinaries.groupby(['flight'])
['total_cost'].agg('sum').to_dict()
flight_n_pass = df_iterinaries.groupby(['flight'])
['n_pass'].agg('sum').to_dict()
df_iterinaries

{"summary":"{\n \"name\": \"df_iterinaries\",\n \"rows\": 1930,\n


\"fields\": [\n {\n \"column\": \"cost\",\n
\"properties\": {\n \"dtype\": \"number\",\n \"std\":
62.387616139128845,\n \"min\": 50.0,\n \"max\": 614.2,\n
\"num_unique_values\": 27,\n \"samples\": [\n 225.0,\n
497.2,\n 468.0\n ],\n \"semantic_type\": \"\",\
n \"description\": \"\"\n }\n },\n {\n
\"column\": \"n_pass\",\n \"properties\": {\n \"dtype\":
\"number\",\n \"std\": 23.708311297570795,\n \"min\":
1.0,\n \"max\": 130.0,\n \"num_unique_values\": 113,\n
\"samples\": [\n 80.0,\n 18.0,\n 88.0\n
],\n \"semantic_type\": \"\",\n \"description\": \"\"\n
}\n },\n {\n \"column\": \"flight\",\n \"properties\":
{\n \"dtype\": \"number\",\n \"std\":
997.4260570847567,\n \"min\": 145.0,\n \"max\": 5166.0,\
n \"num_unique_values\": 463,\n \"samples\": [\n
4706.0,\n 3119.0,\n 4519.0\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"total_cost\",\n
\"properties\": {\n \"dtype\": \"number\",\n \"std\":
4640.31620823028,\n \"min\": 200.0,\n \"max\": 25887.5,\
n \"num_unique_values\": 519,\n \"samples\": [\n
5812.5,\n 2700.0,\n 7012.5\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n }\n ]\n}","type":"dataframe","variable_name":"df_iterinaries"}

from ipywidgets import interact, interactive, fixed, interact_manual

aircraft_flights = df_current_plan.groupby(['aircraft']).apply(lambda
x: x['flight'].tolist()).to_dict()
flight_arcs_for_each_aircraft = {}
deltaplus_flightarcs = {}
deltaminus_flightarcs = {}
for a in aircraft_flights:
aircraft_flights[a] += ['source_%s'%a,'sink_%s'%a]
flight_origin['source_%s'%a] = aircrafts_endpositions_airc[a]
flight_dest['source_%s'%a] = aircrafts_startpositions_airc[a]
flight_origin['sink_%s'%a] = aircrafts_endpositions_airc[a]
flight_dest['sink_%s'%a] = aircrafts_startpositions_airc[a]

flight_start_time['source_%s'%a] = datetime.strptime('0:0', '%H:


%M').time()
flight_end_time['source_%s'%a] = datetime.strptime('0:0', '%H:
%M').time()

flight_start_time['sink_%s'%a] = datetime.strptime('23:59', '%H:


%M').time()
flight_end_time['sink_%s'%a] = datetime.strptime('23:59', '%H:
%M').time()

flight_arcs_for_each_aircraft[a] = []
deltaplus_flightarcs[a] = {f: [] for f in aircraft_flights[a]}
deltaminus_flightarcs[a] = {f: [] for f in aircraft_flights[a]}

for f1 in aircraft_flights[a]:
for f2 in aircraft_flights[a]:
if f1!=f2 and flight_end_time[f1] < flight_start_time[f2]
and flight_dest[f1] == flight_origin[f2]:
flight_arcs_for_each_aircraft[a].append((f1,f2))
deltaplus_flightarcs[a][f1].append(f2)
deltaminus_flightarcs[a][f2].append(f1)
# allow to connect source and target directly for the case
that aircraft is not used at all
elif str(f1).startswith('source') and
str(f2).startswith('sink'):
flight_arcs_for_each_aircraft[a].append((f1,f2))
deltaplus_flightarcs[a][f1].append(f2)
deltaminus_flightarcs[a][f2].append(f1)

# packages needed to visualize the DAG


# uncomment the whole cell in case of troubles
!apt install libgraphviz-dev
!pip install pygraphviz

def visualize_aircraft_network(x):
G = nx.DiGraph()
G.add_edges_from(flight_arcs_for_each_aircraft[x])
plt.figure(figsize=(20,14))
A_graph = to_agraph(G)
A_graph.layout('dot')
display(A_graph)
plt.show()

interact(visualize_aircraft_network, x=aircraft_flights.keys())

Reading package lists... Done


Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
libgail-common libgail18 libgtk2.0-0 libgtk2.0-bin libgtk2.0-common
libgvc6-plugins-gtk librsvg2-common libxdot4
Suggested packages:
gvfs
The following NEW packages will be installed:
libgail-common libgail18 libgraphviz-dev libgtk2.0-0 libgtk2.0-bin
libgtk2.0-common libgvc6-plugins-gtk librsvg2-common libxdot4
0 upgraded, 9 newly installed, 0 to remove and 35 not upgraded.
Need to get 2,434 kB of archives.
After this operation, 7,681 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64
libgtk2.0-common all 2.24.33-2ubuntu2.1 [125 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64
libgtk2.0-0 amd64 2.24.33-2ubuntu2.1 [2,038 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64
libgail18 amd64 2.24.33-2ubuntu2.1 [15.9 kB]
Get:4 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64
libgail-common amd64 2.24.33-2ubuntu2.1 [132 kB]
Get:5 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64
libxdot4 amd64 2.42.2-6ubuntu0.1 [16.4 kB]
Get:6 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64
libgvc6-plugins-gtk amd64 2.42.2-6ubuntu0.1 [22.5 kB]
Get:7 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64
libgraphviz-dev amd64 2.42.2-6ubuntu0.1 [58.5 kB]
Get:8 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64
libgtk2.0-bin amd64 2.24.33-2ubuntu2.1 [7,936 B]
Get:9 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64
librsvg2-common amd64 2.52.5+dfsg-3ubuntu0.2 [17.7 kB]
Fetched 2,434 kB in 1s (2,995 kB/s)
Selecting previously unselected package libgtk2.0-common.
(Reading database ... 126308 files and directories currently
installed.)
Preparing to unpack .../0-libgtk2.0-common_2.24.33-
2ubuntu2.1_all.deb ...
Unpacking libgtk2.0-common (2.24.33-2ubuntu2.1) ...
Selecting previously unselected package libgtk2.0-0:amd64.
Preparing to unpack .../1-libgtk2.0-0_2.24.33-2ubuntu2.1_amd64.deb ...
Unpacking libgtk2.0-0:amd64 (2.24.33-2ubuntu2.1) ...
Selecting previously unselected package libgail18:amd64.
Preparing to unpack .../2-libgail18_2.24.33-2ubuntu2.1_amd64.deb ...
Unpacking libgail18:amd64 (2.24.33-2ubuntu2.1) ...
Selecting previously unselected package libgail-common:amd64.
Preparing to unpack .../3-libgail-common_2.24.33-
2ubuntu2.1_amd64.deb ...
Unpacking libgail-common:amd64 (2.24.33-2ubuntu2.1) ...
Selecting previously unselected package libxdot4:amd64.
Preparing to unpack .../4-libxdot4_2.42.2-6ubuntu0.1_amd64.deb ...
Unpacking libxdot4:amd64 (2.42.2-6ubuntu0.1) ...
Selecting previously unselected package libgvc6-plugins-gtk.
Preparing to unpack .../5-libgvc6-plugins-gtk_2.42.2-
6ubuntu0.1_amd64.deb ...
Unpacking libgvc6-plugins-gtk (2.42.2-6ubuntu0.1) ...
Selecting previously unselected package libgraphviz-dev:amd64.
Preparing to unpack .../6-libgraphviz-dev_2.42.2-
6ubuntu0.1_amd64.deb ...
Unpacking libgraphviz-dev:amd64 (2.42.2-6ubuntu0.1) ...
Selecting previously unselected package libgtk2.0-bin.
Preparing to unpack .../7-libgtk2.0-bin_2.24.33-
2ubuntu2.1_amd64.deb ...
Unpacking libgtk2.0-bin (2.24.33-2ubuntu2.1) ...
Selecting previously unselected package librsvg2-common:amd64.
Preparing to unpack .../8-librsvg2-common_2.52.5+dfsg-
3ubuntu0.2_amd64.deb ...
Unpacking librsvg2-common:amd64 (2.52.5+dfsg-3ubuntu0.2) ...
Setting up libxdot4:amd64 (2.42.2-6ubuntu0.1) ...
Setting up librsvg2-common:amd64 (2.52.5+dfsg-3ubuntu0.2) ...
Setting up libgtk2.0-common (2.24.33-2ubuntu2.1) ...
Setting up libgtk2.0-0:amd64 (2.24.33-2ubuntu2.1) ...
Setting up libgvc6-plugins-gtk (2.42.2-6ubuntu0.1) ...
Setting up libgail18:amd64 (2.24.33-2ubuntu2.1) ...
Setting up libgtk2.0-bin (2.24.33-2ubuntu2.1) ...
Setting up libgail-common:amd64 (2.24.33-2ubuntu2.1) ...
Setting up libgraphviz-dev:amd64 (2.42.2-6ubuntu0.1) ...
Processing triggers for libc-bin (2.35-0ubuntu3.8) ...
/sbin/ldconfig.real: /usr/local/lib/libtbb.so.12 is not a symbolic
link

/sbin/ldconfig.real: /usr/local/lib/libhwloc.so.15 is not a symbolic


link

/sbin/ldconfig.real: /usr/local/lib/libtcm.so.1 is not a symbolic link

/sbin/ldconfig.real: /usr/local/lib/libtbbbind_2_5.so.3 is not a


symbolic link

/sbin/ldconfig.real: /usr/local/lib/libur_loader.so.0 is not a


symbolic link

/sbin/ldconfig.real: /usr/local/lib/libtbbbind.so.3 is not a symbolic


link

/sbin/ldconfig.real: /usr/local/lib/libur_adapter_level_zero.so.0 is
not a symbolic link

/sbin/ldconfig.real: /usr/local/lib/libur_adapter_level_zero_v2.so.0
is not a symbolic link

/sbin/ldconfig.real: /usr/local/lib/libtbbmalloc.so.2 is not a


symbolic link

/sbin/ldconfig.real: /usr/local/lib/libur_adapter_opencl.so.0 is not a


symbolic link

/sbin/ldconfig.real: /usr/local/lib/libtbbmalloc_proxy.so.2 is not a


symbolic link

/sbin/ldconfig.real: /usr/local/lib/libtcm_debug.so.1 is not a


symbolic link

/sbin/ldconfig.real: /usr/local/lib/libumf.so.0 is not a symbolic link

/sbin/ldconfig.real: /usr/local/lib/libtbbbind_2_0.so.3 is not a


symbolic link

Processing triggers for man-db (2.10.2-1) ...


Processing triggers for libgdk-pixbuf-2.0-0:amd64 (2.42.8+dfsg-
1ubuntu0.3) ...
Collecting pygraphviz
Downloading pygraphviz-1.14.tar.gz (106 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 106.0/106.0 kB 5.1 MB/s eta
0:00:00
ents to build wheel ... etadata (pyproject.toml) ... l) ...
e=pygraphviz-1.14-cp311-cp311-linux_x86_64.whl size=169713
sha256=5b436ceb175614b10fb39d9c0d4049c1b469bb50b8e8f1c35ba8217e311d6c8
0
Stored in directory:
/root/.cache/pip/wheels/9c/5f/df/6fffd2a4353f26dbb0e3672a1baf070c124a1
d74a5f9318279
Successfully built pygraphviz
Installing collected packages: pygraphviz
Successfully installed pygraphviz-1.14

{"model_id":"6678de6271ac40ef967a29d034af4237","version_major":2,"vers
ion_minor":0}

<function __main__.visualize_aircraft_network(x)>

Optimization model
%pip install gurobipy
import gurobipy as gp
from gurobipy import GRB
model = gp.Model("airline_disruption")

N = G.nodes()

Collecting gurobipy
Downloading gurobipy-12.0.2-cp311-cp311-
manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (16 kB)
Downloading gurobipy-12.0.2-cp311-cp311-
manylinux2014_x86_64.manylinux_2_17_x86_64.whl (14.5 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/14.5 MB ? eta -:--:--
━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.8/14.5 MB 25.8 MB/s eta
0:00:01 ━━━━━━━━━╸━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.5/14.5 MB 52.3 MB/s
eta 0:00:01 ━━━━━━━━━━━━━━━━━━━━━╸━━━━━━━━━━━━━━━━━━ 7.9/14.5 MB 77.4
MB/s eta 0:00:01 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸ 14.5/14.5 MB
188.7 MB/s eta 0:00:01 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
14.5/14.5 MB 117.7 MB/s eta 0:00:00

x, y = {}, {}
for a in aircrafts:
for f in aircraft_flights[a]:
x[a,f] = model.addVar(name="x_%s,%s"%(a,f), vtype=GRB.BINARY)

for (f1,f2) in flight_arcs_for_each_aircraft[a]:


y[a,f1,f2] = model.addVar(name="y_%s,%s,%s"%(a,f1,f2),
vtype=GRB.BINARY)

model.update()

objective = gp.quicksum((1-x[a,f])*flight_revenue[f] for a in


aircrafts for f in aircraft_flights[a] if f in flight_revenue) #
operating cost
model.setObjective(objective, sense=GRB.MINIMIZE)

for a in aircrafts:
model.addConstr(sum(y[a,'source_%s'%a,f2] for f2 in
deltaplus_flightarcs[a]['source_%s'%a]) == 1)
model.addConstr(sum(y[a,f1,'sink_%s'%a] for f1 in
deltaminus_flightarcs[a]['sink_%s'%a]) == 1)
for f in aircraft_flights[a]:
if str(f)[0] != 's':
model.addConstr(sum(y[a,f,f2] for f2 in
deltaplus_flightarcs[a][f]) == sum(y[a,f1,f] for f1 in
deltaminus_flightarcs[a][f]))

for a in aircrafts:
for f in aircraft_flights[a]:
model.addConstr(x[a,f] <= sum(y[a,f,f2] for f2 in
deltaplus_flightarcs[a][f])) # flight f is chosen only if it is
traversed

alpha = .5

for i in N:
total_departures = len([f for a in aircrafts for f in
aircraft_flights[a] if flight_origin[f] == i])
total_arrivals = len([f for a in aircrafts for f in
aircraft_flights[a] if flight_dest[f] == i])

model.addConstr(sum(x[a,f] for a in aircrafts for f in


aircraft_flights[a] if flight_origin[f] == i) <=
alpha*total_departures)
model.addConstr(sum(x[a,f] for a in aircrafts for f in
aircraft_flights[a] if flight_dest[f] == i) <= alpha*total_arrivals)

model.optimize()

Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - "Ubuntu


22.04.4 LTS")

CPU model: AMD EPYC 7B12, instruction set [SSE2|AVX|AVX2]


Thread count: 1 physical cores, 2 logical processors, using up to 2
threads

Optimize a model with 536 rows, 1930 columns and 5772 nonzeros
Model fingerprint: 0x0ae86089
Variable types: 0 continuous, 1930 integer (1930 binary)
Coefficient statistics:
Matrix range [1e+00, 1e+00]
Objective range [6e+03, 6e+04]
Bounds range [1e+00, 1e+00]
RHS range [1e+00, 6e+01]
Found heuristic solution: objective 1878476.0000
Presolve removed 498 rows and 1569 columns
Presolve time: 0.02s
Presolved: 38 rows, 361 columns, 722 nonzeros
Found heuristic solution: objective 561087.00000
Variable types: 0 continuous, 361 integer (343 binary)

Explored 0 nodes (0 simplex iterations) in 0.05 seconds (0.01 work


units)
Thread count was 2 (of 2 available processors)

Solution count 2: 561087 1.87848e+06

Optimal solution found (tolerance 1.00e-04)


Best objective 5.610870000000e+05, best bound 5.610870000000e+05, gap
0.0000%

Optimal solution
operated_flights = {a: [f for f in aircraft_flights[a] if x[a,f].X >
.5 if str(f)[0] != 's'] for a in aircrafts}

print("\nNet revenue total loss:


$",round(model.objVal/10**6,2),'million')
print("Optimal number of flights served:",sum(len(operated_flights[a])
for a in aircrafts))
print("Optimal number of passengers
transported:",sum(sum(flight_n_pass[f] for f in aircraft_flights[a] if
x[a,f].X > .5) for a in aircrafts))
print("Optimal number of aircrafts utilized:",sum([1 if
len(operated_flights[a]) > 0 else 0 for a in aircrafts]))

Net revenue total loss: $ 0.56 million


Optimal number of flights served: 51
Optimal number of passengers transported: 6570.0
Optimal number of aircrafts utilized: 9

import gurobipy as gp
from gurobipy import GRB
from ipywidgets import interact, interactive, fixed, interact_manual,
widgets

N = G.nodes()

def solve_flight_planning(x):
alpha = x

model = gp.Model("airline_disruption")
x, y = {}, {}
for a in aircrafts:
for f in aircraft_flights[a]:
x[a,f] = model.addVar(name="x_%s,%s"%(a,f),
vtype=GRB.BINARY)

for (f1,f2) in flight_arcs_for_each_aircraft[a]:


y[a,f1,f2] = model.addVar(name="y_%s,%s,%s"%(a,f1,f2),
vtype=GRB.BINARY)

model.update()

objective = gp.quicksum((1-x[a,f])*flight_revenue[f] for a in


aircrafts for f in aircraft_flights[a] if f in flight_revenue) #
operating cost
model.setObjective(objective, sense=GRB.MINIMIZE)

for a in aircrafts:
model.addConstr(sum(y[a,'source_%s'%a,f2] for f2 in
deltaplus_flightarcs[a]['source_%s'%a]) == 1)
model.addConstr(sum(y[a,f1,'sink_%s'%a] for f1 in
deltaminus_flightarcs[a]['sink_%s'%a]) == 1)
for f in aircraft_flights[a]:
if str(f)[0] != 's':
model.addConstr(sum(y[a,f,f2] for f2 in
deltaplus_flightarcs[a][f]) == sum(y[a,f1,f] for f1 in
deltaminus_flightarcs[a][f]))

for a in aircrafts:
for f in aircraft_flights[a]:
model.addConstr(x[a,f] <= sum(y[a,f,f2] for f2 in
deltaplus_flightarcs[a][f])) # flight f is chosen only if it is
traversed

for i in N:
total_departures = len([f for a in aircrafts for f in
aircraft_flights[a] if flight_origin[f] == i])
total_arrivals = len([f for a in aircrafts for f in
aircraft_flights[a] if flight_dest[f] == i])
model.addConstr(sum(x[a,f] for a in aircrafts for f in
aircraft_flights[a] if flight_origin[f] == i) <=
alpha*total_departures)
model.addConstr(sum(x[a,f] for a in aircrafts for f in
aircraft_flights[a] if flight_dest[f] == i) <= alpha*total_arrivals)

model.setParam('OutputFlag', 0)
model.optimize()

operated_flights = {a: [f for f in aircraft_flights[a] if x[a,f].X


> .5 if str(f)[0] != 's'] for a in aircrafts}
actual_rev = sum(flight_revenue[f] for f in flight_revenue) #
operating cost
print("Loss ($): ",round(model.objVal/10**6,2),'million')
print("Optimal number of flights
served:",sum(len(operated_flights[a]) for a in aircrafts))
print("Optimal number of passengers
transported:",sum(sum(flight_n_pass[f] for f in aircraft_flights[a] if
x[a,f].X > .5) for a in aircrafts))
print("Optimal number of aircrafts utilized:",sum([1 if
len(operated_flights[a]) > 0 else 0 for a in aircrafts]))

# the following lines are for visualization and needs the package
pygraphviz (can be commented in case of troubles)
print("Full network of operated flights:")
G = nx.MultiDiGraph()
arcs=[(flight_origin[f],flight_dest[f]) for a in aircrafts for f
in operated_flights[a]]

aircraft_color =
{aircrafts[i]:"#"+''.join([random.choice('0123456789ABCDEF') for j in
range(6)]) for i in range(len(aircrafts))}
for a in aircrafts:
for f in operated_flights[a]:

G.add_edge(flight_origin[f],flight_dest[f],color=aircraft_color[a])
A_graph = to_agraph(G)
A_graph.layout('dot')
display(A_graph)

print("Select a value for the level of disruption at the airports:\n")


print("Select 0 for complete shutdown of all airports; select 1 for
business-as-usual.\n")

interact(solve_flight_planning, x=(0,1,0.05))

Select a value for the level of disruption at the airports:

Select 0 for complete shutdown of all airports; select 1 for business-


as-usual.

{"model_id":"8a2574d7d992416d882b8ebba1399e61","version_major":2,"vers
ion_minor":0}

<function __main__.solve_flight_planning(x)>

model.dispose()
gp.disposeDefaultEnv()

Freeing default Gurobi environment

You might also like