overbooking / accc.py
FelipeRocha13's picture
Upload accc.py
e5bda07 verified
import math
from math import comb
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import streamlit as st
# ----------------- Funções auxiliares -----------------
def prob_binom(n, k, p):
if k < 0 or k > n:
return 0.0
return comb(n, k) * (p**k) * ((1-p)**(n-k))
def prob_overbooking(n, c, p):
k_vals = np.arange(c+1, n+1)
if len(k_vals) == 0:
return 0.0
probs = [prob_binom(n, int(k), p) for k in k_vals]
return float(np.sum(probs))
def expected_bumped(n, c, p):
ks = np.arange(c+1, n+1)
if len(ks) == 0:
return 0.0
vals = [(k - c) * prob_binom(n, int(k), p) for k in ks]
return float(np.sum(vals))
def expected_profit(n, c, p, R, C_marg, C_over):
EX = n * p
E_bumped = expected_bumped(n, c, p)
return n*R - EX*C_marg - E_bumped*C_over
# ----------------- Interface Streamlit -----------------
st.title("Análise de Overbooking - Aérea Confiável ✈️")
# Parâmetros de entrada
st.sidebar.header("Parâmetros")
capacidade = st.sidebar.number_input("Capacidade do avião", min_value=50, max_value=300, value=120)
vendidas_alvo = st.sidebar.number_input("Passagens vendidas", min_value=capacidade, max_value=capacidade+50, value=130)
p_comparecer = st.sidebar.slider("Probabilidade de comparecimento (%)", 0.5, 1.0, 0.88, 0.01)
R = st.sidebar.number_input("Receita média por bilhete (R$)", min_value=100.0, value=800.0, step=50.0)
C_marg = st.sidebar.number_input("Custo marginal por passageiro presente (R$)", min_value=50.0, value=150.0, step=10.0)
C_over = st.sidebar.number_input("Custo médio por passageiro preterido (R$)", min_value=500.0, value=1500.0, step=50.0)
# ----------------- Cálculos -----------------
# Probabilidade para cenário alvo
prob_over_130 = prob_overbooking(vendidas_alvo, capacidade, p_comparecer)
st.subheader("1️⃣ Probabilidade de Overbooking")
st.write(f"Com **{vendidas_alvo} passagens vendidas**, capacidade de **{capacidade}**, e p={p_comparecer:.2f}, a probabilidade de overbooking é:")
st.metric("Risco de Overbooking", f"{prob_over_130*100:.2f}%")
# ----------------- Variação do risco -----------------
n_min = capacidade
n_max = capacidade + 30
Ns = list(range(n_min, n_max + 1))
probs = [prob_overbooking(n, capacidade, p_comparecer) for n in Ns]
df_risco = pd.DataFrame({
"Passagens Vendidas": Ns,
"Probabilidade Overbooking (%)": [p*100 for p in probs]
})
limite = 0.07
viaveis = df_risco[df_risco["Probabilidade Overbooking (%)"] <= limite*100]
st.subheader("2️⃣ Variação do risco por número de passagens vendidas")
st.dataframe(df_risco)
# Gráfico
fig, ax = plt.subplots()
ax.plot(df_risco["Passagens Vendidas"], df_risco["Probabilidade Overbooking (%)"])
ax.axhline(limite*100, linestyle="--", label="Limite 7%")
ax.set_title("Risco de Overbooking x Passagens Vendidas")
ax.set_xlabel("Passagens Vendidas")
ax.set_ylabel("Probabilidade (%)")
ax.grid(True)
ax.legend()
st.pyplot(fig)
# ----------------- Análise Financeira -----------------
st.subheader("3️⃣ Análise Financeira")
cenarios = [capacidade + d for d in [0, 5, 10, 15]]
resultados = []
for n in cenarios:
lucro = expected_profit(n, capacidade, p_comparecer, R, C_marg, C_over)
risco = prob_overbooking(n, capacidade, p_comparecer)
bumped_esp = expected_bumped(n, capacidade, p_comparecer)
resultados.append({
"Passagens Vendidas": n,
"Probabilidade Overbooking (%)": round(risco*100, 3),
"Passageiros Preteridos (Esperado)": round(bumped_esp, 2),
"Lucro Esperado (R$)": round(lucro, 2)
})
df_fin = pd.DataFrame(resultados)
st.dataframe(df_fin)
st.write("""
- O risco aumenta conforme mais passagens são vendidas.
- O lucro pode crescer até certo ponto, mas o custo de overbooking pode inviabilizar a estratégia.
- O objetivo é equilibrar **risco aceitável (<=7%)** e **maximização do lucro**.
""")