import pandas as pd import numpy as np import requests import json import time from datetime import datetime, timedelta import plotly.graph_objs as go import plotly.express as px from plotly.subplots import make_subplots import gradio as gr from dataclasses import dataclass from typing import List, Dict, Tuple import threading import queue import random # Configuration class FleetConfig: def __init__(self): self.num_vehicles = 50 self.vehicle_capacity = 4 self.max_distance = 100 # km self.base_cost_per_km = 0.5 self.weather_impact = { 'clear': 1.0, 'rain': 1.2, 'snow': 1.5, 'storm': 2.0 } self.traffic_impact = { 'low': 1.0, 'medium': 1.3, 'high': 1.8, 'severe': 2.5 } @dataclass class Vehicle: id: int location: Tuple[float, float] # lat, lng status: str # 'available', 'busy', 'maintenance' capacity: int current_load: int total_distance: float earnings: float last_update: datetime @dataclass class Demand: id: int pickup_location: Tuple[float, float] dropoff_location: Tuple[float, float] passengers: int priority: int # 1-5, 5 being highest timestamp: datetime status: str # 'pending', 'assigned', 'completed' @dataclass class WeatherData: location: Tuple[float, float] condition: str temperature: float wind_speed: float visibility: float timestamp: datetime @dataclass class TrafficData: location: Tuple[float, float] congestion_level: str # 'low', 'medium', 'high', 'severe' average_speed: float delay_minutes: float timestamp: datetime class FleetOptimizer: def __init__(self): self.config = FleetConfig() self.vehicles = [] self.demands = [] self.weather_data = {} self.traffic_data = {} self.simulation_running = False self.data_queue = queue.Queue() # Initialize vehicles self._initialize_vehicles() # Simulation parameters self.simulation_time = datetime.now() self.time_step = 60 # seconds def _initialize_vehicles(self): """Initialize fleet vehicles with random locations""" for i in range(self.config.num_vehicles): vehicle = Vehicle( id=i, location=(random.uniform(40.7, 40.8), random.uniform(-74.0, -73.9)), # NYC area status='available', capacity=self.config.vehicle_capacity, current_load=0, total_distance=0.0, earnings=0.0, last_update=datetime.now() ) self.vehicles.append(vehicle) def generate_demand(self): """Generate realistic demand patterns""" # Simulate demand hotspots hotspots = [ (40.7589, -73.9851), # Times Square (40.7505, -73.9934), # Penn Station (40.7527, -73.9772), # Grand Central (40.7484, -73.9857), # Empire State Building (40.7587, -73.9787), # Rockefeller Center ] # Generate demand based on time patterns hour = self.simulation_time.hour base_demand_rate = 0.3 # Increased base rate # Peak hours (7-9 AM, 5-7 PM) if 7 <= hour <= 9 or 17 <= hour <= 19: base_demand_rate = 0.6 # Higher peak rate elif 22 <= hour or hour <= 6: base_demand_rate = 0.1 # Higher night rate # Generate multiple demands per step num_demands = random.choices([0, 1, 2], weights=[0.4, 0.4, 0.2])[0] for _ in range(num_demands): if random.random() < base_demand_rate: pickup = random.choice(hotspots) dropoff = ( pickup[0] + random.uniform(-0.01, 0.01), pickup[1] + random.uniform(-0.01, 0.01) ) demand = Demand( id=len(self.demands), pickup_location=pickup, dropoff_location=dropoff, passengers=random.randint(1, 4), priority=random.randint(1, 5), timestamp=self.simulation_time, status='pending' ) self.demands.append(demand) def update_weather_data(self): """Simulate weather data updates""" # Simulate weather conditions conditions = ['clear', 'rain', 'snow', 'storm'] weights = [0.7, 0.2, 0.08, 0.02] # Mostly clear weather for vehicle in self.vehicles: condition = random.choices(conditions, weights=weights)[0] weather = WeatherData( location=vehicle.location, condition=condition, temperature=random.uniform(-5, 35), wind_speed=random.uniform(0, 30), visibility=random.uniform(0.1, 10), timestamp=self.simulation_time ) self.weather_data[vehicle.id] = weather def update_traffic_data(self): """Simulate traffic data updates""" # Traffic patterns based on time hour = self.simulation_time.hour if 7 <= hour <= 9 or 17 <= hour <= 19: congestion_levels = ['medium', 'high', 'severe'] weights = [0.3, 0.5, 0.2] else: congestion_levels = ['low', 'medium', 'high'] weights = [0.6, 0.3, 0.1] for vehicle in self.vehicles: congestion = random.choices(congestion_levels, weights=weights)[0] traffic = TrafficData( location=vehicle.location, congestion_level=congestion, average_speed=random.uniform(10, 60), delay_minutes=random.uniform(0, 15), timestamp=self.simulation_time ) self.traffic_data[vehicle.id] = traffic def calculate_distance(self, loc1, loc2): """Calculate distance between two locations (simplified)""" return np.sqrt((loc1[0] - loc2[0])**2 + (loc1[1] - loc2[1])**2) * 111 # km def calculate_cost(self, vehicle_id, pickup_loc, dropoff_loc): """Calculate cost considering weather and traffic""" distance = self.calculate_distance(pickup_loc, dropoff_loc) # Get weather and traffic impacts weather = self.weather_data.get(vehicle_id) traffic = self.traffic_data.get(vehicle_id) weather_multiplier = self.config.weather_impact.get(weather.condition, 1.0) if weather else 1.0 traffic_multiplier = self.config.traffic_impact.get(traffic.congestion_level, 1.0) if traffic else 1.0 total_cost = distance * self.config.base_cost_per_km * weather_multiplier * traffic_multiplier return total_cost, distance def optimize_vehicle_allocation(self): """AI-powered vehicle allocation optimization""" pending_demands = [d for d in self.demands if d.status == 'pending'] available_vehicles = [v for v in self.vehicles if v.status == 'available'] if not pending_demands or not available_vehicles: return # Create cost matrix for assignment problem cost_matrix = [] for vehicle in available_vehicles: vehicle_costs = [] for demand in pending_demands: cost, distance = self.calculate_cost(vehicle.id, vehicle.location, demand.pickup_location) # Add penalty for distance and priority penalty = distance * 0.1 + (6 - demand.priority) * 2 total_cost = cost + penalty vehicle_costs.append(total_cost) cost_matrix.append(vehicle_costs) # Simple greedy assignment (can be improved with Hungarian algorithm) assignments = [] used_vehicles = set() used_demands = set() # Sort demands by priority (highest first) sorted_demands = sorted(pending_demands, key=lambda x: x.priority, reverse=True) for demand in sorted_demands: best_vehicle = None best_cost = float('inf') for i, vehicle in enumerate(available_vehicles): if i in used_vehicles: continue if vehicle.current_load + demand.passengers <= vehicle.capacity: cost = cost_matrix[i][pending_demands.index(demand)] if cost < best_cost: best_cost = cost best_vehicle = i if best_vehicle is not None: assignments.append((available_vehicles[best_vehicle], demand)) used_vehicles.add(best_vehicle) used_demands.add(demand.id) # Execute assignments (limit to prevent all vehicles being assigned at once) max_assignments = min(len(assignments), 5) # Max 5 assignments per step for vehicle, demand in assignments[:max_assignments]: self._assign_vehicle_to_demand(vehicle, demand) def _assign_vehicle_to_demand(self, vehicle, demand): """Assign vehicle to demand and update status""" vehicle.status = 'busy' vehicle.current_load = demand.passengers demand.status = 'assigned' # Calculate trip details pickup_distance = self.calculate_distance(vehicle.location, demand.pickup_location) trip_distance = self.calculate_distance(demand.pickup_location, demand.dropoff_location) # Update vehicle metrics vehicle.total_distance += pickup_distance + trip_distance vehicle.earnings += self.calculate_cost(vehicle.id, demand.pickup_location, demand.dropoff_location)[0] vehicle.location = demand.dropoff_location vehicle.last_update = self.simulation_time # Simulate trip completion after some time completion_time = self.simulation_time + timedelta(minutes=random.randint(5, 20)) self.data_queue.put(('complete_trip', vehicle.id, completion_time)) def complete_trips(self): """Complete trips that have finished""" current_time = self.simulation_time # Check for completed trips while not self.data_queue.empty(): try: action, vehicle_id, completion_time = self.data_queue.get_nowait() if action == 'complete_trip' and completion_time <= current_time: vehicle = next(v for v in self.vehicles if v.id == vehicle_id) vehicle.status = 'available' vehicle.current_load = 0 except queue.Empty: break def run_simulation_step(self): """Run one simulation step""" if not self.simulation_running: return # Update simulation time (advance by 1 hour for more realistic demand patterns) self.simulation_time = self.simulation_time + timedelta(hours=1) # Generate new demand self.generate_demand() # Update weather and traffic data self.update_weather_data() self.update_traffic_data() # Complete finished trips self.complete_trips() # Optimize vehicle allocation self.optimize_vehicle_allocation() def start_simulation(self): """Start the simulation""" self.simulation_running = True print("🚗 Fleet optimization simulation started!") while self.simulation_running: self.run_simulation_step() time.sleep(1) # Real-time simulation def stop_simulation(self): """Stop the simulation""" self.simulation_running = False print("🛑 Simulation stopped") def get_simulation_stats(self): """Get current simulation statistics""" total_earnings = sum(v.earnings for v in self.vehicles) total_distance = sum(v.total_distance for v in self.vehicles) available_vehicles = len([v for v in self.vehicles if v.status == 'available']) busy_vehicles = len([v for v in self.vehicles if v.status == 'busy']) pending_demands = len([d for d in self.demands if d.status == 'pending']) return { 'total_earnings': total_earnings, 'total_distance': total_distance, 'available_vehicles': available_vehicles, 'busy_vehicles': busy_vehicles, 'pending_demands': pending_demands, 'simulation_time': self.simulation_time.strftime('%H:%M:%S'), 'total_demands': len(self.demands) } def create_dashboard(self): """Create interactive dashboard""" # Vehicle locations vehicle_locations = pd.DataFrame([ { 'id': v.id, 'lat': v.location[0], 'lng': v.location[1], 'status': v.status, 'earnings': v.earnings, 'distance': v.total_distance } for v in self.vehicles ]) # Demand locations demand_locations = pd.DataFrame([ { 'id': d.id, 'lat': d.pickup_location[0], 'lng': d.pickup_location[1], 'status': d.status, 'priority': d.priority } for d in self.demands if d.status in ['pending', 'assigned'] ]) # Create map fig = go.Figure() # Add vehicle markers for status in ['available', 'busy']: vehicles = vehicle_locations[vehicle_locations['status'] == status] if not vehicles.empty: fig.add_trace(go.Scattermapbox( lat=vehicles['lat'], lon=vehicles['lng'], mode='markers', marker=go.scattermapbox.Marker( size=10, color='green' if status == 'available' else 'red' ), name=f'Vehicles ({status})', text=vehicles['id'], hovertemplate='Vehicle %{text}
Earnings: $%{customdata[0]:.2f}
Distance: %{customdata[1]:.1f}km', customdata=vehicles[['earnings', 'distance']].values )) # Add demand markers if not demand_locations.empty: fig.add_trace(go.Scattermapbox( lat=demand_locations['lat'], lon=demand_locations['lng'], mode='markers', marker=go.scattermapbox.Marker( size=8, color='blue', symbol='diamond' ), name='Demands', text=demand_locations['id'], hovertemplate='Demand %{text}
Priority: %{customdata}', customdata=demand_locations['priority'] )) fig.update_layout( mapbox=dict( style='open-street-map', center=dict(lat=40.7589, lon=-73.9851), zoom=12 ), title='Fleet Optimization Dashboard', height=600 ) return fig # Global optimizer instance optimizer = FleetOptimizer() def start_fleet_simulation(): """Start the fleet optimization simulation""" if not optimizer.simulation_running: thread = threading.Thread(target=optimizer.start_simulation, daemon=True) thread.start() return "🚗 Fleet optimization simulation started! Check the dashboard for real-time updates." return "Simulation is already running!" def stop_fleet_simulation(): """Stop the fleet optimization simulation""" optimizer.stop_simulation() return "🛑 Simulation stopped" def get_fleet_stats(): """Get current fleet statistics""" stats = optimizer.get_simulation_stats() return json.dumps(stats, indent=2) def update_fleet_dashboard(): """Update the fleet dashboard""" return optimizer.create_dashboard() # Gradio interface def create_fleet_interface(): with gr.Blocks(title="Fleet Resource Optimization Simulator", theme=gr.themes.Soft()) as demo: gr.Markdown("# 🚗 Fleet Resource Optimization with AI Agents") gr.Markdown("### Dynamic vehicle allocation based on traffic, weather, and demand") with gr.Row(): with gr.Column(scale=1): gr.Markdown("### 🎮 Simulation Controls") start_btn = gr.Button("🚀 Start Simulation", variant="primary") stop_btn = gr.Button("🛑 Stop Simulation", variant="secondary") gr.Markdown("### 📊 Real-time Statistics") stats_btn = gr.Button("📈 Update Stats") stats_output = gr.Textbox(label="Fleet Statistics", lines=10, interactive=False) gr.Markdown("### ⚙️ Configuration") gr.Markdown(f""" - **Total Vehicles**: {optimizer.config.num_vehicles} - **Vehicle Capacity**: {optimizer.config.vehicle_capacity} passengers - **Max Distance**: {optimizer.config.max_distance} km - **Base Cost**: ${optimizer.config.base_cost_per_km}/km """) with gr.Column(scale=2): gr.Markdown("### 🗺️ Live Fleet Dashboard") dashboard_output = gr.Plot(label="Vehicle Locations & Demand") # Event handlers start_btn.click( fn=start_fleet_simulation, outputs=gr.Textbox(label="Status", lines=2) ) stop_btn.click( fn=stop_fleet_simulation, outputs=gr.Textbox(label="Status", lines=2) ) stats_btn.click( fn=get_fleet_stats, outputs=stats_output ) # Auto-refresh dashboard demo.load( fn=update_fleet_dashboard, outputs=dashboard_output ) # Periodic updates demo.load( fn=lambda: None, every=5 # Update every 5 seconds ) return demo if __name__ == "__main__": demo = create_fleet_interface() demo.launch(share=True)