GitHub Actions
Deploy App to HF Spaces
63cc479
Raw History Blame Contribute Delete
9.28 kB
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]