fester/scheduler/optimizer.py

97 lines
2.3 KiB
Python

# scheduler/optimizer.py
def choose_best_node(nodes, action, intelligence=None):
best_node = None
best_score = -10**9
ranked = []
# -----------------------------
# SCORE EACH NODE
# -----------------------------
for node in nodes:
breakdown = {
"cpu": 0,
"thermal": 0,
"policy": 0,
"intelligence": 0,
"final": 0
}
# CPU availability
cpu_score = (100 - node.get("cpu_load", 0))
breakdown["cpu"] = cpu_score
# Thermal penalty
thermal_penalty = node.get("temp", 0)
breakdown["thermal"] = -thermal_penalty
# Policy rules
policy_score = 0
if node.get("policy") == "preferred":
policy_score += 20
elif node.get("policy") == "avoid":
policy_score -= 50
breakdown["policy"] = policy_score
# Intelligence feedback
intel_score = 0
if intelligence:
stats = intelligence.profiles.get(action["target"])
if stats:
latest = stats.finalize()
intel_score -= latest["score"].get("thermal", 0) * 0.3
intel_score -= latest["score"].get("instability", 0) * 0.2
breakdown["intelligence"] = intel_score
# Final score
final = cpu_score + policy_score + intel_score + breakdown["thermal"]
breakdown["final"] = final
ranked.append({
"node": node,
"score": breakdown
})
if final > best_score:
best_score = final
best_node = node
# -----------------------------
# SORT FOR EXPLANATION
# -----------------------------
ranked_sorted = sorted(
ranked,
key=lambda x: x["score"]["final"],
reverse=True
)
# -----------------------------
# EXPLANATION OBJECT
# -----------------------------
explanation = {
"selected": best_node["name"] if best_node else None,
"top_candidates": [
{
"node": r["node"]["name"],
"final_score": r["score"]["final"],
"breakdown": r["score"]
}
for r in ranked_sorted[:5]
]
}
return {
"best_node": best_node,
"ranked": ranked,
"explanation": explanation
}