Upload runner.py
Browse files
runner.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Episode runner with persistent pheromone across churn."""
|
| 2 |
+
import numpy as np, sim, schedulers as sch
|
| 3 |
+
|
| 4 |
+
SCHEDULERS = {
|
| 5 |
+
"RoundRobin": lambda ctx, st, **k: sch.round_robin(ctx),
|
| 6 |
+
"LeastConn": lambda ctx, st, **k: sch.least_connection(ctx),
|
| 7 |
+
"ACO": lambda ctx, st, **k: sch.standalone_aco(ctx, iters=k["iters"], state=st),
|
| 8 |
+
"PSO": lambda ctx, st, **k: sch.standalone_pso(ctx, iters=k["iters"]),
|
| 9 |
+
"WOA": lambda ctx, st, **k: sch.woa(ctx, iters=k["iters"]),
|
| 10 |
+
"AdaptiSwarm": lambda ctx, st, **k: sch.adaptiswarm_edge(ctx, iters=k["iters"], sigma_u=k.get("sigma_u",0.0), state=st),
|
| 11 |
+
"Abl_ACOonly": lambda ctx, st, **k: sch.adaptiswarm_edge(ctx, iters=k["iters"], use_pso=False, sigma_u=k.get("sigma_u",0.0), state=st),
|
| 12 |
+
"Abl_PSOrand": lambda ctx, st, **k: sch.adaptiswarm_edge(ctx, iters=k["iters"], use_aco_seed=False, use_adaptive=False, sigma_u=k.get("sigma_u",0.0), state=st),
|
| 13 |
+
"Abl_PSOseed": lambda ctx, st, **k: sch.adaptiswarm_edge(ctx, iters=k["iters"], use_adaptive=False, sigma_u=k.get("sigma_u",0.0), state=st),
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
def run_episode(name, n_nodes, lam, seed, n_steps=15, iters=40,
|
| 17 |
+
alpha=0.5, beta=0.3, gamma=0.2, churn=True, probe_step=8):
|
| 18 |
+
rng = np.random.default_rng(seed)
|
| 19 |
+
nodes = sim.make_nodes(n_nodes, rng)
|
| 20 |
+
cap, mem, p_idle, p_peak = sim.node_arrays(nodes)
|
| 21 |
+
link_lat = sim.make_link_latency(n_nodes, rng)
|
| 22 |
+
active = np.ones(n_nodes, dtype=bool); backlog = np.zeros(n_nodes); state = {}
|
| 23 |
+
agg = dict(latency=[], energy=[], util=[], jain=[], A_met=[], all_met=[], sigma=[])
|
| 24 |
+
conv_curve = None; prev_util = np.zeros(n_nodes)
|
| 25 |
+
for step in range(n_steps):
|
| 26 |
+
if churn and n_nodes >= 5:
|
| 27 |
+
if rng.random() < 0.3:
|
| 28 |
+
idx = rng.integers(n_nodes); active[idx] = not active[idx]
|
| 29 |
+
if active.sum() < max(2, n_nodes // 3):
|
| 30 |
+
active[:] = True
|
| 31 |
+
act_idx = np.where(active)[0]
|
| 32 |
+
a_cap = cap[act_idx]; a_mem = mem[act_idx]; a_link = link_lat[act_idx]
|
| 33 |
+
a_pidle = p_idle[act_idx]; a_ppeak = p_peak[act_idx]; a_backlog = backlog[act_idx]
|
| 34 |
+
n_arr = rng.poisson(lam * sim.DT)
|
| 35 |
+
demand, tmem, deadline, cls = sim.make_tasks(n_arr, rng)
|
| 36 |
+
sigma_u_live = float(np.std(prev_util[act_idx])) if act_idx.size else 0.0
|
| 37 |
+
ctx = sch.Ctx(demand, tmem, deadline, cls, a_backlog, a_cap, a_link,
|
| 38 |
+
a_pidle, a_ppeak, alpha, beta, gamma, rng, node_mem=a_mem)
|
| 39 |
+
local_state = {}
|
| 40 |
+
for gkey in ("aco", "adapti"):
|
| 41 |
+
gtau = state.get("global_" + gkey)
|
| 42 |
+
if gtau is not None: local_state[gkey] = gtau[act_idx].copy()
|
| 43 |
+
assign, curve = SCHEDULERS[name](ctx, local_state, iters=iters, sigma_u=sigma_u_live)
|
| 44 |
+
for gkey in ("aco", "adapti"):
|
| 45 |
+
if gkey in local_state:
|
| 46 |
+
gtau = state.get("global_" + gkey)
|
| 47 |
+
if gtau is None: gtau = np.ones(n_nodes)
|
| 48 |
+
gtau[act_idx] = local_state[gkey]; state["global_" + gkey] = gtau
|
| 49 |
+
if n_arr > 0:
|
| 50 |
+
mtr = sim.evaluate(assign, demand, tmem, deadline, cls, a_backlog,
|
| 51 |
+
a_cap, a_link, a_pidle, a_ppeak, alpha, beta,
|
| 52 |
+
gamma, return_metrics=True, node_mem=a_mem)
|
| 53 |
+
for k,mk in [("latency","avg_latency"),("energy","energy"),("util","utilization"),
|
| 54 |
+
("jain","jain"),("A_met","classA_deadline_met"),("all_met","all_deadline_met"),("sigma","sigma_u")]:
|
| 55 |
+
agg[k].append(mtr[mk])
|
| 56 |
+
added = np.zeros(len(act_idx))
|
| 57 |
+
for j,n in enumerate(assign): added[n] += demand[j]
|
| 58 |
+
backlog[act_idx] = np.maximum(a_backlog + added - a_cap * sim.DT, 0.0)
|
| 59 |
+
prev_util = np.zeros(n_nodes); prev_util[act_idx] = mtr["served"] / (a_cap * sim.DT)
|
| 60 |
+
else:
|
| 61 |
+
backlog[act_idx] = np.maximum(a_backlog - a_cap * sim.DT, 0.0)
|
| 62 |
+
if step == probe_step and len(curve) > 1: conv_curve = curve
|
| 63 |
+
def stat(key):
|
| 64 |
+
v = np.array(agg[key]) if agg[key] else np.array([0.0]); return v.mean()
|
| 65 |
+
conv_iter = iters
|
| 66 |
+
if conv_curve is not None and len(conv_curve) > 1:
|
| 67 |
+
final = conv_curve[-1]; rs = abs(conv_curve[0] - final) + 1e-9
|
| 68 |
+
for i,f in enumerate(conv_curve):
|
| 69 |
+
if abs(f - final) <= 0.02 * rs: conv_iter = i + 1; break
|
| 70 |
+
return dict(latency_ms=stat("latency")*1000.0, utilization=stat("util")*100.0,
|
| 71 |
+
energy=stat("energy"), jain=stat("jain"),
|
| 72 |
+
A_deadline=stat("A_met")*100.0, all_deadline=stat("all_met")*100.0,
|
| 73 |
+
conv_iter=conv_iter, conv_curve=conv_curve)
|