Compare commits

...

3 Commits

View File

@@ -207,20 +207,24 @@ with tab2:
# --- TAB 3: SOLVER --- # --- TAB 3: SOLVER ---
with tab3: with tab3:
st.header("Mathematical Formulation") st.header("Mathematical Formulation")
st.latex(r"\min \sum_{t} \sum_{r} (c_{r} \cdot x_{r,t}) + \sum_{t} \sum_{d} (M \cdot s_{d,t})") st.latex(r"\min \sum_{m,e,r,t} (c_{m,e,r} \cdot x_{m,e,r,t})")
st.latex(r"\text{s.t.} \quad \sum_{m,e} (\text{cap}_{m} \cdot x_{m,e,r,t}) + s_{r,t} \ge \text{PAX}_{r,t} \quad \forall r, t") st.latex(r"\text{s.t.} \quad \sum_{m,e} (\text{cap}_{m} \cdot x_{m,e,r,t}) \ge \text{PAX}_{r,t} \quad \forall r, t")
st.latex(r"\sum_{t_{start} \le T \le t_{start} + \text{pernoites}} x_{m,e,r,t_{start}} \le \text{MaxFleet}_{m,e} \quad \forall m, e, T") st.latex(r"\sum_{t_{start} \le T \le t_{start} + \text{overnights}} x_{m,e,r,t_{start}} \le \text{MaxFleet}_{m,e} \quad \forall m, e, T")
st.latex(r"\text{FlightTime}_{m,r} \cdot x_{m,e,r,t} \le \text{MaxDailyHours} \quad \forall m,e,r,t")
st.latex(r"\text{MissionTime}_{m,r} \le \text{MaxDaysOut} \quad \forall m,r")
st.markdown(r""" st.markdown(r"""
**Dictionary of Variables:** **Dictionary of Variables & Constraints:**
- $x_{m,e,r,t}$: Decision Variable (Integer). Number of aircraft of model $m$, from squadron $e$, allocated to route $r$ on day $t$. - $x_{m,e,r,t}$: Decision Variable (Integer). Number of aircraft of model $m$, from squadron $e$, allocated to route $r$ on day $t$.
- $c_r$: Estimated total fuel cost for the route $r$ mission, including overnight stay penalties if applicable. - $c_{m,e,r}$: Total fuel cost function: $c_{m,e,r} = \left( \frac{\text{Dist}_r \cdot \text{RangePenalty}}{\text{FuelConsumption}_m} \right) + (\text{overnights} \cdot \text{DailyPenalty}_m)$.
- $s_{r,t}$: Slack Variable. Represents the passenger demand that could **not** be met on that day due to fleet limitations. - $\text{RangePenalty}$: Applies a **25% penalty** multiplier ($1.25$) to the fuel burn if any leg of the mission exceeds the aircraft's maximum range.
- $M$: High Penalty (Big M). Imposed on the system for each unit of slack activated, forcing the solver to meet demand whenever possible. - $\text{DailyPenalty}_m$: Equivalent to an extra daily fuel expenditure quota for each day the aircraft spends out of its base.
- $\text{cap}_m$: Maximum passenger capacity (seats) of aircraft $m$. - $\text{cap}_m$: Maximum passenger capacity (seats) of aircraft $m$.
- $\text{PAX}_{r,t}$: Actual number of Air Force passengers needing to fly on route $r$ on day $t$. - $\text{PAX}_{r,t}$: Actual number of Air Force passengers needing to fly on route $r$ on day $t$.
- $\text{MaxFleet}_{m,e}$: Total physical aircraft available in squadron $e$ for model $m$. - $\text{MaxFleet}_{m,e}$: Total physical aircraft available in squadron $e$ for model $m$.
- $T$: Temporal inspection window. Ensures aircraft blockade during overnight stays, preventing fleet duplication. - $T$: Temporal inspection window. Ensures aircraft blockade during overnight stays, preventing fleet duplication.
- $\text{MaxDailyHours}$: Maximum allowed flight time per day per aircraft (typically $12$ hours).
- $\text{MaxDaysOut}$: Maximum allowable time for a mission before returning to base (hard limit of $96$ hours / 4 days).
""") """)
if st.button("🚀 Run Global Optimization", type="primary"): if st.button("🚀 Run Global Optimization", type="primary"):
@@ -229,7 +233,8 @@ with tab3:
if run_solver_subprocess(300, log_placeholder): if run_solver_subprocess(300, log_placeholder):
st.success("Solver Finished! Results saved to CSV.") st.success("Solver Finished! Results saved to CSV.")
st.session_state['new_results'] = True load_results.clear()
st.rerun()
else: else:
st.error("Solver Failed or was aborted.") st.error("Solver Failed or was aborted.")
@@ -237,9 +242,6 @@ with tab3:
with tab4: with tab4:
st.header("Interactive Flight Map") st.header("Interactive Flight Map")
if st.session_state.get('new_results'):
df_results = load_results()
view_state = pdk.ViewState(latitude=-15.78, longitude=-47.92, zoom=3.5, pitch=45) view_state = pdk.ViewState(latitude=-15.78, longitude=-47.92, zoom=3.5, pitch=45)
layers = [] layers = []