PranavKK1201 commited on
Commit
3a871a0
Β·
1 Parent(s): 5144b7e

fixed task 1, 2, 3

Browse files
Files changed (4) hide show
  1. grader.py +27 -10
  2. models.py +5 -0
  3. server/AntiAtropos_environment.py +1 -0
  4. simulator.py +12 -0
grader.py CHANGED
@@ -60,23 +60,36 @@ class Grade:
60
 
61
  Weights deliberately penalise cost heavily so that brute-force
62
  SCALE_UP spam cannot achieve a high composite even with perfect uptime.
63
- A purely reactive agent that always SCALE_UPs is bounded by:
64
- 0.4 * 1.0 + 0.2 * 1.0 + 0.4 * ~0.0 β‰ˆ 0.60 (worst-case)
65
- An intelligent agent that right-sizes capacity can reach 0.9+.
 
66
  """
67
- return (
68
- 0.4 * self.scores["uptime"] +
69
- 0.2 * self.scores["stability"] +
70
- 0.4 * self.scores["cost"]
71
- )
 
 
 
 
 
 
 
 
 
72
 
73
  def summary(self) -> str:
74
  s = self.scores
75
- return (
76
  f"[{self.task_id}] composite={self.composite:.3f} | "
77
  f"uptime={s['uptime']:.3f} | cost={s['cost']:.3f} | "
78
  f"stability={s['stability']:.3f} | SLA violations={int(s['violations'])}/101"
79
  )
 
 
 
80
 
81
 
82
  class EpisodeGrader:
@@ -135,11 +148,15 @@ class EpisodeGrader:
135
  ratio = avg_energy / TARGET_ENERGY
136
  stability_score = 1.0 / (1.0 + (ratio ** STABILITY_CURVE_POWER))
137
 
 
 
 
138
  return Grade(self.task_id, {
139
  "uptime": uptime_score,
140
  "cost": cost_score,
141
  "stability": stability_score,
142
- "violations": total_violations
 
143
  })
144
 
145
 
 
60
 
61
  Weights deliberately penalise cost heavily so that brute-force
62
  SCALE_UP spam cannot achieve a high composite even with perfect uptime.
63
+
64
+ Hardening:
65
+ - Task 3 coupling: Cost only rewards if Uptime is >= 50%. Stops 'Cheap-but-Dead'.
66
+ - Invalid Action Penalty: -0.05 per forbidden command (SHED_LOAD on critical).
67
  """
68
+ uptime = self.scores["uptime"]
69
+ stability = self.scores["stability"]
70
+ cost = self.scores["cost"]
71
+ invalid_penalty = self.scores.get("invalid_actions", 0) * 0.05
72
+
73
+ if self.task_id == "task-3":
74
+ # Coupling: If uptime < 0.5, the cost benefit is zeroed out.
75
+ # Mirroring real-world priority: Budget doesn't matter if the site is down.
76
+ cost_weight = 1.0 if uptime >= 0.5 else 0.0
77
+ score = (0.4 * uptime + 0.2 * stability + 0.4 * (cost * cost_weight))
78
+ else:
79
+ score = (0.4 * uptime + 0.2 * stability + 0.4 * cost)
80
+
81
+ return max(0.0, score - invalid_penalty)
82
 
83
  def summary(self) -> str:
84
  s = self.scores
85
+ summary = (
86
  f"[{self.task_id}] composite={self.composite:.3f} | "
87
  f"uptime={s['uptime']:.3f} | cost={s['cost']:.3f} | "
88
  f"stability={s['stability']:.3f} | SLA violations={int(s['violations'])}/101"
89
  )
90
+ if s.get("invalid_actions", 0) > 0:
91
+ summary += f" | INVALID ACTIONS={int(s['invalid_actions'])}"
92
+ return summary
93
 
94
 
95
  class EpisodeGrader:
 
148
  ratio = avg_energy / TARGET_ENERGY
149
  stability_score = 1.0 / (1.0 + (ratio ** STABILITY_CURVE_POWER))
150
 
151
+ # ── 4. Invalid Action tracking ──────────────────────────────────────
152
+ total_invalid = self._records[-1].get("invalid_action_count", 0)
153
+
154
  return Grade(self.task_id, {
155
  "uptime": uptime_score,
156
  "cost": cost_score,
157
  "stability": stability_score,
158
+ "violations": total_violations,
159
+ "invalid_actions": total_invalid
160
  })
161
 
162
 
models.py CHANGED
@@ -124,6 +124,11 @@ class ClusterObservation(BaseModel):
124
  description="Cumulative count of SLA violations this episode.",
125
  )
126
 
 
 
 
 
 
127
  nodes: list[NodeObservation]
128
 
129
  # Episode interaction fields (handled by framework)
 
124
  description="Cumulative count of SLA violations this episode.",
125
  )
126
 
127
+ invalid_action_count: int = Field(
128
+ default=0,
129
+ description="Number of forbidden actions (e.g. SHED_LOAD on critical nodes).",
130
+ )
131
+
132
  nodes: list[NodeObservation]
133
 
134
  # Episode interaction fields (handled by framework)
server/AntiAtropos_environment.py CHANGED
@@ -206,6 +206,7 @@ class AntiAtroposEnvironment(Environment):
206
  step=self._state.step_count,
207
  max_steps=MAX_STEPS,
208
  sla_violations=self._sla_violations,
 
209
  done=False,
210
  reward=0.0,
211
  )
 
206
  step=self._state.step_count,
207
  max_steps=MAX_STEPS,
208
  sla_violations=self._sla_violations,
209
+ invalid_action_count=self._sim.invalid_action_count,
210
  done=False,
211
  reward=0.0,
212
  )
simulator.py CHANGED
@@ -55,6 +55,10 @@ T3_SURGE_BASE_END: int = 40 # Nominal end of surge within cycle
55
  T3_SURGE_JITTER: int = 10 # Β±jitter applied to start/end each episode
56
  T3_SURGE_MAGNITUDE: float = 70.0 # Extra req/tick added to node-1 and node-2
57
 
 
 
 
 
58
 
59
  class NodeStatus(str, Enum):
60
  HEALTHY = "HEALTHY"
@@ -132,6 +136,7 @@ class ClusterSimulator:
132
  # Per-node reroute weights for REROUTE_TRAFFIC (node_id β†’ fraction)
133
  self._reroute_weights: dict[str, float] = {}
134
  self._nodes: list[NodeState] = []
 
135
  self._randomize_domain()
136
  self._reset_nodes()
137
 
@@ -166,6 +171,7 @@ class ClusterSimulator:
166
  self._tick_count = 0
167
  self._failed_node_id = None
168
  self._reroute_weights = {}
 
169
  self._randomize_domain()
170
  self._reset_nodes()
171
 
@@ -217,6 +223,12 @@ class ClusterSimulator:
217
  self._reroute_weights[node_id] = frac
218
 
219
  elif at == "SHED_LOAD":
 
 
 
 
 
 
220
  frac = min(1.0, param)
221
  target.shed_fraction = frac
222
  # Note: physically applied in _update_queues() to incoming traffic
 
55
  T3_SURGE_JITTER: int = 10 # Β±jitter applied to start/end each episode
56
  T3_SURGE_MAGNITUDE: float = 70.0 # Extra req/tick added to node-1 and node-2
57
 
58
+ # Hardening: Critical infrastructure that CANNOT be shed
59
+ # In Task 3, these receive the surge. Forcing the agent to SCALE.
60
+ CRITICAL_NODES: list[str] = ["node-0", "node-1", "node-2"]
61
+
62
 
63
  class NodeStatus(str, Enum):
64
  HEALTHY = "HEALTHY"
 
136
  # Per-node reroute weights for REROUTE_TRAFFIC (node_id β†’ fraction)
137
  self._reroute_weights: dict[str, float] = {}
138
  self._nodes: list[NodeState] = []
139
+ self.invalid_action_count: int = 0
140
  self._randomize_domain()
141
  self._reset_nodes()
142
 
 
171
  self._tick_count = 0
172
  self._failed_node_id = None
173
  self._reroute_weights = {}
174
+ self.invalid_action_count = 0
175
  self._randomize_domain()
176
  self._reset_nodes()
177
 
 
223
  self._reroute_weights[node_id] = frac
224
 
225
  elif at == "SHED_LOAD":
226
+ # Rule: Cannot shed critical nodes (database/control plane).
227
+ # This forces the agent to handle Task-3 surge via Scaling/Rerouting.
228
+ if node_id in CRITICAL_NODES:
229
+ self.invalid_action_count += 1
230
+ return
231
+
232
  frac = min(1.0, param)
233
  target.shed_fraction = frac
234
  # Note: physically applied in _update_queues() to incoming traffic