Spaces:
Sleeping
Sleeping
| """ | |
| Main application entry point for Hugging Face Spaces. | |
| """ | |
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| import plotly.graph_objects as go | |
| from datetime import datetime, timedelta | |
| # Simple in-memory data storage | |
| class AppState: | |
| def __init__(self): | |
| self.data = None | |
| self.forecast = None | |
| app_state = AppState() | |
| def load_sample_data(dataset_name): | |
| """Load or generate sample data.""" | |
| try: | |
| # Generate synthetic data | |
| dates = pd.date_range(start='2023-01-01', periods=365, freq='D') | |
| if "Retail" in dataset_name: | |
| # Retail pattern with weekly seasonality | |
| base = 100 | |
| trend = np.linspace(0, 20, 365) | |
| seasonal = 20 * np.sin(2 * np.pi * np.arange(365) / 7) | |
| noise = np.random.normal(0, 5, 365) | |
| values = base + trend + seasonal + noise | |
| elif "Walmart" in dataset_name: | |
| # Walmart M5 style | |
| base = 150 | |
| trend = np.linspace(0, 30, 365) | |
| weekly = 40 * np.sin(2 * np.pi * np.arange(365) / 7) | |
| noise = np.random.normal(0, 10, 365) | |
| values = base + trend + weekly + noise | |
| else: | |
| # Synthetic random walk | |
| values = 100 + np.cumsum(np.random.randn(365) * 5) | |
| values = np.maximum(values, 10) # Keep positive | |
| data = pd.DataFrame({ | |
| 'date': dates, | |
| 'value': values | |
| }) | |
| app_state.data = data | |
| # Create stats | |
| stats = f""" | |
| 📊 Dataset Statistics: | |
| • Total Rows: {len(data)} | |
| • Date Range: {data['date'].min().date()} to {data['date'].max().date()} | |
| • Mean Value: {data['value'].mean():.2f} | |
| • Std Dev: {data['value'].std():.2f} | |
| • Min Value: {data['value'].min():.2f} | |
| • Max Value: {data['value'].max():.2f} | |
| """ | |
| # Create plot | |
| fig = go.Figure() | |
| fig.add_trace(go.Scatter( | |
| x=data['date'], | |
| y=data['value'], | |
| mode='lines', | |
| name='Historical Data', | |
| line=dict(color='blue', width=2) | |
| )) | |
| fig.update_layout( | |
| title="Time Series Data", | |
| xaxis_title="Date", | |
| yaxis_title="Value", | |
| template='plotly_white', | |
| height=400 | |
| ) | |
| return data.head(100), stats, fig, "✅ Data loaded successfully!" | |
| except Exception as e: | |
| return None, f"❌ Error: {str(e)}", None, "Failed to load data" | |
| def simple_forecast(horizon): | |
| """Generate simple moving average forecast.""" | |
| try: | |
| if app_state.data is None: | |
| return None, "❌ Please load data first!", "Please load data in Data Upload tab" | |
| data = app_state.data | |
| # Simple moving average forecast | |
| window = min(30, len(data) // 2) | |
| ma = data['value'].tail(window).mean() | |
| std = data['value'].tail(window).std() | |
| # Generate future dates | |
| last_date = data['date'].iloc[-1] | |
| future_dates = pd.date_range(start=last_date + timedelta(days=1), periods=horizon, freq='D') | |
| # Simple forecast | |
| forecast_values = np.ones(horizon) * ma | |
| lower = forecast_values - 1.96 * std | |
| upper = forecast_values + 1.96 * std | |
| forecast_df = pd.DataFrame({ | |
| 'date': future_dates, | |
| 'forecast': forecast_values, | |
| 'lower_bound': lower, | |
| 'upper_bound': upper | |
| }) | |
| app_state.forecast = forecast_df | |
| # Create plot | |
| fig = go.Figure() | |
| # Historical | |
| fig.add_trace(go.Scatter( | |
| x=data['date'], | |
| y=data['value'], | |
| mode='lines', | |
| name='Historical', | |
| line=dict(color='blue', width=2) | |
| )) | |
| # Forecast | |
| fig.add_trace(go.Scatter( | |
| x=forecast_df['date'], | |
| y=forecast_df['forecast'], | |
| mode='lines', | |
| name='Forecast', | |
| line=dict(color='red', width=2, dash='dash') | |
| )) | |
| # Confidence interval | |
| fig.add_trace(go.Scatter( | |
| x=forecast_df['date'].tolist() + forecast_df['date'].tolist()[::-1], | |
| y=forecast_df['upper_bound'].tolist() + forecast_df['lower_bound'].tolist()[::-1], | |
| fill='toself', | |
| fillcolor='rgba(255,0,0,0.2)', | |
| line=dict(color='rgba(255,255,255,0)'), | |
| name='95% Confidence', | |
| showlegend=True | |
| )) | |
| fig.update_layout( | |
| title=f"{horizon}-Day Forecast", | |
| xaxis_title="Date", | |
| yaxis_title="Value", | |
| template='plotly_white', | |
| height=400 | |
| ) | |
| info = f""" | |
| 📈 Forecast Information: | |
| • Model: Moving Average (Simple) | |
| • Horizon: {horizon} days | |
| • Mean Forecast: {forecast_values.mean():.2f} | |
| • Confidence Level: 95% | |
| """ | |
| return fig, info, "✅ Forecast generated successfully!" | |
| except Exception as e: | |
| return None, f"❌ Error: {str(e)}", "Forecast generation failed" | |
| def calculate_eoq(): | |
| """Calculate Economic Order Quantity.""" | |
| try: | |
| if app_state.forecast is None: | |
| return "❌ Please generate forecast first!", "" | |
| # Simple EOQ calculation | |
| annual_demand = app_state.forecast['forecast'].sum() * (365 / len(app_state.forecast)) | |
| ordering_cost = 100.0 | |
| holding_cost = 10.0 * 0.20 | |
| # EOQ formula | |
| eoq = np.sqrt(2 * annual_demand * ordering_cost / holding_cost) | |
| num_orders = annual_demand / eoq | |
| total_cost = (num_orders * ordering_cost) + ((eoq / 2) * holding_cost) | |
| results = f""" | |
| 📦 Inventory Optimization Results (EOQ Model): | |
| • Optimal Order Quantity: {eoq:.2f} units | |
| • Number of Orders per Year: {num_orders:.2f} | |
| • Order Cycle Time: {365 / num_orders:.1f} days | |
| • Total Annual Cost: ${total_cost:.2f} | |
| - Ordering Cost: ${num_orders * ordering_cost:.2f} | |
| - Holding Cost: ${(eoq / 2) * holding_cost:.2f} | |
| • Annual Demand: {annual_demand:.2f} units | |
| """ | |
| recommendations = f""" | |
| 💡 Recommendations: | |
| • Place an order of {eoq:.0f} units every {365 / num_orders:.0f} days | |
| • Maintain safety stock of {eoq * 0.2:.0f} units | |
| • Monitor demand patterns for adjustments | |
| """ | |
| return results, recommendations | |
| except Exception as e: | |
| return f"❌ Error: {str(e)}", "" | |
| # Create Gradio interface | |
| with gr.Blocks(title="ForecastIQ Pro", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown(""" | |
| # 🎯 ForecastIQ Pro | |
| **AI-Powered Demand Forecasting & Inventory Optimization** | |
| """) | |
| with gr.Tabs(): | |
| # Tab 1: Data Upload | |
| with gr.Tab("📁 Data Upload"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| dataset_selector = gr.Radio( | |
| choices=["Sample: Retail Sales", "Sample: Walmart M5", "Sample: Synthetic"], | |
| label="Select Dataset", | |
| value="Sample: Retail Sales" | |
| ) | |
| load_btn = gr.Button("Load Data", variant="primary") | |
| status_text = gr.Textbox(label="Status", lines=1) | |
| with gr.Column(): | |
| data_stats = gr.Textbox(label="Statistics", lines=8) | |
| data_preview = gr.Dataframe(label="Data Preview") | |
| data_plot = gr.Plot(label="Time Series Visualization") | |
| load_btn.click( | |
| load_sample_data, | |
| inputs=[dataset_selector], | |
| outputs=[data_preview, data_stats, data_plot, status_text] | |
| ) | |
| # Tab 2: Forecasting | |
| with gr.Tab("🔮 Forecasting"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| horizon_slider = gr.Slider( | |
| minimum=7, | |
| maximum=90, | |
| value=30, | |
| step=1, | |
| label="Forecast Horizon (days)" | |
| ) | |
| forecast_btn = gr.Button("Generate Forecast", variant="primary") | |
| forecast_status = gr.Textbox(label="Status", lines=1) | |
| with gr.Column(): | |
| forecast_info = gr.Textbox(label="Forecast Information", lines=8) | |
| forecast_plot = gr.Plot(label="Forecast Results") | |
| forecast_btn.click( | |
| simple_forecast, | |
| inputs=[horizon_slider], | |
| outputs=[forecast_plot, forecast_info, forecast_status] | |
| ) | |
| # Tab 3: Optimization | |
| with gr.Tab("📦 Inventory Optimization"): | |
| gr.Markdown("### Economic Order Quantity (EOQ) Model") | |
| optimize_btn = gr.Button("Calculate Optimal Inventory", variant="primary") | |
| with gr.Row(): | |
| opt_results = gr.Textbox(label="Optimization Results", lines=12) | |
| opt_recommendations = gr.Textbox(label="Recommendations", lines=12) | |
| optimize_btn.click( | |
| calculate_eoq, | |
| inputs=[], | |
| outputs=[opt_results, opt_recommendations] | |
| ) | |
| gr.Markdown(""" | |
| --- | |
| ### 📚 About ForecastIQ Pro | |
| A production-grade platform for demand forecasting and inventory optimization. | |
| Combines time series analysis with operations research for data-driven decision making. | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch(share=True) | |