| import time |
| import random |
| import networkx as nx |
| import matplotlib.pyplot as plt |
|
|
| |
| |
| |
| class VenueLayout: |
| def __init__(self): |
| |
| self.graph = nx.DiGraph() |
| self._build_venue() |
|
|
| def _build_venue(self): |
| """ |
| Defines a realistic stadium/convention center layout. |
| Format: (Source, Destination, Base Walking Time, Maximum Person Capacity) |
| """ |
| connections = [ |
| |
| ('Main_Gate_A', 'Walkway_North', 2, 50), |
| ('Main_Gate_B', 'Walkway_South', 2, 30), |
| |
| |
| ('Walkway_North', 'Food_Court_1', 3, 40), |
| ('Walkway_South', 'Food_Court_2', 3, 40), |
| |
| |
| ('Food_Court_1', 'Arena_Zone_X', 4, 60), |
| ('Food_Court_2', 'Arena_Zone_Y', 4, 60), |
| ('Walkway_North', 'Arena_Zone_X', 5, 80), |
| ('Walkway_South', 'Arena_Zone_Y', 5, 80), |
| |
| |
| ('Walkway_North', 'Walkway_South', 3, 25), |
| ('Walkway_South', 'Walkway_North', 3, 25), |
| |
| |
| ('Arena_Zone_X', 'Main_Exit_1', 3, 50), |
| ('Arena_Zone_Y', 'Main_Exit_2', 3, 50), |
| ] |
| |
| for src, dest, weight, capacity in connections: |
| self.graph.add_edge(src, dest, weight=weight, capacity=capacity, current_load=0) |
|
|
| def update_edge_load(self, src, dest, count): |
| """Updates the current number of people occupying a specific pathway.""" |
| if self.graph.has_edge(src, dest): |
| self.graph[src][dest]['current_load'] = count |
|
|
| def get_dynamic_weight(self, src, dest): |
| """ |
| GOOGLE GPS LOGIC: Path cost increases exponentially as it fills up. |
| If a path is full (bottlenecked), it creates artificial 'traffic delay'. |
| """ |
| edge = self.graph[src][dest] |
| load = edge['current_load'] |
| capacity = edge['capacity'] |
| base_time = edge['weight'] |
| |
| if load >= capacity: |
| return base_time * 10.0 |
| elif load >= capacity * 0.75: |
| return base_time * 3.5 |
| elif load >= capacity * 0.50: |
| return base_time * 1.8 |
| return base_time |
|
|
| |
| |
| |
| class PersonAgent: |
| def __init__(self, agent_id, origin, destination): |
| self.agent_id = agent_id |
| self.origin = origin |
| self.destination = destination |
| self.current_node = origin |
| self.route = [] |
| self.route_index = 0 |
| self.completed = False |
|
|
| def calculate_route(self, venue_layout, use_rerouting=True): |
| """Calculates or updates paths based on live navigation data.""" |
| try: |
| if use_rerouting: |
| |
| self.route = nx.shortest_path( |
| venue_layout.graph, |
| source=self.current_node, |
| target=self.destination, |
| weight=venue_layout.get_dynamic_weight |
| ) |
| else: |
| |
| self.route = nx.shortest_path( |
| venue_layout.graph, |
| source=self.current_node, |
| target=self.destination, |
| weight='weight' |
| ) |
| self.route_index = 0 |
| except nx.NetworkNoPath: |
| pass |
|
|
| def step(self): |
| """Moves the agent along their designated path sequence.""" |
| if self.current_node == self.destination: |
| self.completed = True |
| return self.current_node, None |
| |
| if self.route_index < len(self.route) - 1: |
| from_node = self.route[self.route_index] |
| to_node = self.route[self.route_index + 1] |
| self.current_node = to_node |
| self.route_index += 1 |
| return from_node, to_node |
| else: |
| self.completed = True |
| return self.current_node, None |
|
|
| |
| |
| |
| class CrowdFlowOptimiser: |
| def __init__(self, crowd_size=150, use_ai_rerouting=True): |
| self.venue = VenueLayout() |
| self.crowd_size = crowd_size |
| self.use_ai_rerouting = use_ai_rerouting |
| self.agents = [] |
| self.history_metrics = [] |
| self._initialize_crowd() |
|
|
| def _initialize_crowd(self): |
| """Populates the venue with simulated visitors based on schedules.""" |
| origins = ['Main_Gate_A', 'Main_Gate_B'] |
| destinations = ['Arena_Zone_X', 'Arena_Zone_Y', 'Main_Exit_1', 'Main_Exit_2'] |
| |
| |
| random.seed(42) |
| |
| for i in range(self.crowd_size): |
| start = random.choice(origins) |
| end = random.choice(destinations) |
| agent = PersonAgent(agent_id=i, origin=start, destination=end) |
| self.agents.append(agent) |
|
|
| def run_simulation_step(self): |
| """Executes a single frame slice of the global crowd timeline.""" |
| |
| for u, v in self.venue.graph.edges(): |
| self.venue.graph[u][v]['current_load'] = 0 |
| |
| |
| active_agents = [a for a in self.agents if not a.completed] |
| if not active_agents: |
| return False |
|
|
| for agent in active_agents: |
| agent.calculate_route(self.venue, use_rerouting=self.use_ai_rerouting) |
| |
| |
| for agent in active_agents: |
| u, v = agent.step() |
| if v is not None: |
| self.venue.graph[u][v]['current_load'] += 1 |
| |
| return True |
|
|
| def detect_bottlenecks(self): |
| """Analyzes all edge vectors matching threshold metrics.""" |
| bottlenecks = {} |
| for u, v, data in self.venue.graph.edges(data=True): |
| load = data['current_load'] |
| cap = data['capacity'] |
| ratio = load / cap if cap > 0 else 0 |
| |
| if ratio >= 0.75: |
| bottlenecks[f"{u} -> {v}"] = { |
| "Severity": "CRITICAL RED ZONE" if ratio >= 1.0 else "WARNING AMBER ZONE", |
| "Density": f"{load}/{cap} people" |
| } |
| return bottlenecks |
|
|
| |
| |
| |
| def run_inference_pipeline(crowd_size=200, enable_rerouting=True): |
| """ |
| Standard automated function wrapper matching model pipeline interfaces. |
| """ |
| print(f"๐ Initializing AI Evaluator Pipeline Instance (Size: {crowd_size}, Rerouting Engine: {enable_rerouting})") |
| optimiser = CrowdFlowOptimiser(crowd_size=crowd_size, use_ai_rerouting=enable_rerouting) |
| |
| step = 0 |
| max_steps = 20 |
| is_running = True |
| |
| while is_running and step < max_steps: |
| step += 1 |
| is_running = optimiser.run_simulation_step() |
| live_bottlenecks = optimiser.detect_bottlenecks() |
| |
| print(f"\n--- TIME STEP T+{step} ---") |
| if live_bottlenecks: |
| print("๐จ BOTTLENECK ZONES DETECTED:") |
| for path, info in live_bottlenecks.items(): |
| print(f" ๐ Route [{path}] -> Status: {info['Severity']} ({info['Density']})") |
| else: |
| print("๐ข Clear Flow Across All Vectors. Google Map Traffic Index: Normal") |
| |
| print("\nโ
Simulation Evaluation Finished cleanly.") |
| return {"status": "SUCCESS", "evaluated_steps": step} |
|
|
| if __name__ == "__main__": |
| |
| run_inference_pipeline(crowd_size=220, enable_rerouting=True) |
|
|