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**. """)