Spaces:
Runtime error
Runtime error
File size: 9,277 Bytes
63cc479 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | import asyncio
import random
import math
import networkx as nx
from app.core.state import sim_state
from app.core.config import DATA_GEN_RATE_MB_STEP, MAX_BUFFER_MB, WIFI_RANGE_METERS
from app.simulation.utils import euclidean_dist
def init_sim_entities():
nodes = list(sim_state.graph.nodes(data=True))
sim_state.hubs = []
sim_state.vehicles = []
sim_state.step = 0
sim_state.total_generated_mb = 0.0
sim_state.total_offloaded_mb = 0.0
sim_state.total_buffer_overflows = 0
sim_state.priority_latency_sum = 0
sim_state.priority_events_completed = 0
sim_state.recent_events = []
center_lat = 33.6515
center_lon = 73.0801
top_right_nodes = [n for n in nodes if n[1]["y"] > center_lat + 0.005 and n[1]["x"] > center_lon + 0.005]
if len(top_right_nodes) >= 2 and sim_state.num_hubs >= 2:
tr_hubs = random.sample(top_right_nodes, 2)
other_nodes = [n for n in nodes if n not in tr_hubs]
hub_nodes = tr_hubs + random.sample(other_nodes, sim_state.num_hubs - 2)
else:
hub_nodes = random.sample(nodes, sim_state.num_hubs)
for hid, node in enumerate(hub_nodes):
sim_state.hubs.append({
"id": hid,
"lat": node[1]["y"],
"lon": node[1]["x"],
"range": WIFI_RANGE_METERS,
"rate": random.choice([1.0, 2.5, 5.0]),
"active": False,
"online": True,
"total_offloaded_mb": 0.0
})
node_ids = list(sim_state.graph.nodes())
for vid in range(sim_state.num_vehicles):
n1 = random.choice(node_ids)
n2 = random.choice(node_ids)
try:
path = nx.shortest_path(sim_state.graph, n1, n2, weight='length')
except:
path = [n1]
start_data = sim_state.graph.nodes[n1]
target_lat = start_data["y"]
target_lon = start_data["x"]
if len(path) > 1:
next_node = path[1]
target_lat = sim_state.graph.nodes[next_node]["y"]
target_lon = sim_state.graph.nodes[next_node]["x"]
base_spd = random.uniform(0.00004, 0.00008)
sim_state.vehicles.append({
"id": vid,
"lat": start_data["y"],
"lon": start_data["x"],
"buffer_mb": 0.0,
"routine_mb": 0.0,
"priority_mb": 0.0,
"panic": False,
"target_lat": target_lat,
"target_lon": target_lon,
"path": path,
"path_idx": 1 if len(path) > 1 else 0,
"base_speed": base_spd,
"speed": base_spd,
"events": []
})
async def simulation_loop():
while True:
if sim_state.running:
run_step()
await asyncio.sleep(0.05)
def run_step():
sim_state.step += 1
for hub in sim_state.hubs:
hub["active"] = False
if random.random() < 0.001:
hub["online"] = not hub["online"]
node_ids = list(sim_state.graph.nodes())
edge_traffic = {}
for v in sim_state.vehicles:
if v["path"] and v["path_idx"] < len(v["path"]):
prev = v["path"][v["path_idx"]-1] if v["path_idx"] > 0 else v["path"][0]
curr = v["path"][v["path_idx"]]
edge_traffic[(prev, curr)] = edge_traffic.get((prev, curr), 0) + 1
EVENT_TYPES = ["Pothole", "Minor Crash", "Debris", "Speed Trap", "Traffic Jam"]
for v in sim_state.vehicles:
v["routine_mb"] += DATA_GEN_RATE_MB_STEP
sim_state.total_generated_mb += DATA_GEN_RATE_MB_STEP
if v["path"] and v["path_idx"] < len(v["path"]):
prev = v["path"][v["path_idx"]-1] if v["path_idx"] > 0 else v["path"][0]
curr = v["path"][v["path_idx"]]
vehicles_on_edge = edge_traffic.get((prev, curr), 1)
v["speed"] = v["base_speed"] / max(1, vehicles_on_edge)
if random.random() < sim_state.event_rate:
evt_type = random.choice(EVENT_TYPES)
evt_size = random.uniform(5.0, 10.0)
v["events"].append({"type": evt_type, "size": evt_size, "timestamp": sim_state.step})
v["priority_mb"] += evt_size
sim_state.total_generated_mb += evt_size
total_buf = v["routine_mb"] + v["priority_mb"]
if total_buf > MAX_BUFFER_MB:
overflow_amt = total_buf - MAX_BUFFER_MB
dropped_mb = min(overflow_amt, v["routine_mb"])
if dropped_mb > 0:
v["routine_mb"] -= dropped_mb
sim_state.total_buffer_overflows += 1
v["buffer_mb"] = v["routine_mb"] + v["priority_mb"]
dx = v["target_lon"] - v["lon"]
dy = v["target_lat"] - v["lat"]
dist = math.sqrt(dx*dx + dy*dy)
if dist < v["speed"]:
v["lon"] = v["target_lon"]
v["lat"] = v["target_lat"]
v["path_idx"] += 1
if v["path_idx"] < len(v["path"]):
next_node = v["path"][v["path_idx"]]
v["target_lat"] = sim_state.graph.nodes[next_node]["y"]
v["target_lon"] = sim_state.graph.nodes[next_node]["x"]
else:
start_node = v["path"][-1] if v["path"] else random.choice(node_ids)
end_node = random.choice(node_ids)
try:
new_path = nx.shortest_path(sim_state.graph, start_node, end_node, weight='length')
except:
new_path = [start_node]
v["path"] = new_path
v["path_idx"] = 1
if len(new_path) > 1:
next_node = new_path[1]
v["target_lat"] = sim_state.graph.nodes[next_node]["y"]
v["target_lon"] = sim_state.graph.nodes[next_node]["x"]
else:
v["target_lat"] = v["lat"]
v["target_lon"] = v["lon"]
else:
v["lon"] += (dx/dist) * v["speed"]
v["lat"] += (dy/dist) * v["speed"]
closest_hub = None
min_dist = float('inf')
for hub in sim_state.hubs:
d = euclidean_dist(v["lat"], v["lon"], hub["lat"], hub["lon"])
if d < min_dist:
min_dist = d
closest_hub = hub
if closest_hub and min_dist <= closest_hub["range"]:
if not closest_hub["online"]:
v["panic"] = True
else:
skip_offload = False
if sim_state.algorithm == "predictive" and not v.get("panic", False) and (v["routine_mb"] + v["priority_mb"]) < MAX_BUFFER_MB * 0.8:
future_nodes = v["path"][v["path_idx"]:v["path_idx"]+10]
for f_node in future_nodes:
ny = sim_state.graph.nodes[f_node]["y"]
nx_coord = sim_state.graph.nodes[f_node]["x"]
for h in sim_state.hubs:
if h["online"] and h["rate"] > closest_hub["rate"] and euclidean_dist(ny, nx_coord, h["lat"], h["lon"]) <= h["range"]:
skip_offload = True
break
if skip_offload:
break
if not skip_offload:
amt_to_offload = closest_hub["rate"]
while v["events"] and amt_to_offload > 0:
evt = v["events"][0]
if evt["size"] <= amt_to_offload:
amt_to_offload -= evt["size"]
v["priority_mb"] -= evt["size"]
sim_state.total_offloaded_mb += evt["size"]
closest_hub["total_offloaded_mb"] += evt["size"]
latency = sim_state.step - evt["timestamp"]
sim_state.priority_latency_sum += latency
sim_state.priority_events_completed += 1
v["events"].pop(0)
sim_state.recent_events.insert(0, f"[{sim_state.step}] Veh {v['id']} offloaded '{evt['type']}' to Hub {closest_hub['id']} (Lat: {latency}s)")
else:
evt["size"] -= amt_to_offload
v["priority_mb"] -= amt_to_offload
sim_state.total_offloaded_mb += amt_to_offload
closest_hub["total_offloaded_mb"] += amt_to_offload
amt_to_offload = 0
if amt_to_offload > 0 and v["routine_mb"] > 0:
off_routine = min(v["routine_mb"], amt_to_offload)
v["routine_mb"] -= off_routine
sim_state.total_offloaded_mb += off_routine
closest_hub["total_offloaded_mb"] += off_routine
closest_hub["active"] = True
v["panic"] = False
v["buffer_mb"] = v["routine_mb"] + v["priority_mb"]
sim_state.recent_events = sim_state.recent_events[:30]
|