Overheat Prevention Controller
Problem statement
Implement a controller that manages the temperature of a multicore processor. Workload changes are deferred until the next Tick. Each tick settles temperatures and shutdowns, applies pending loads, and then chooses active cooling for the next interval.
Core state and thermal rules
- At time
0, every core is running with temperature20, load0, and active cooling off. A running core isidlewhen active cooling is off andcoolingwhen it is on. - Each core has a passive-cooling demand of
load + 2watts. A shut-down core has load0and still receives passive cooling. - Let
kbe the number of cores with active cooling on. LetF[1], F[2], ... = 1, 2, 3, 5, .... Effective shared passive capacity ispooledCooling * (1 - sum(0.1 / F[j], j = 1..k)). - If that capacity meets the total demand, every core receives its full demand. Otherwise, distribute it proportionally: core
ireceiveseffectiveCapacity * demand[i] / totalDemand. - An actively cooled core receives exactly
activeCooling[i]additional watts of cooling. - Temperature changes at
0.02degrees per second per watt of net heat, where net heat isload - passiveCooling - activeCoolingIfOn. Temperature cannot fall below20. - For this exercise, use the loads and cooling choices from the preceding tick throughout the interval until the next tick. At that next tick, settle every temperature with these frozen rates, clamp to the ambient floor, and then shut down each running core whose observed temperature is at least
80. Clear its load and active cooling. Do not clamp its temperature to80.
Deferred loads and restarts
The arrays operations and operationData form one finite call sequence. Every row begins with a timestamp in seconds. Timestamps are strictly increasing, starting at a nonnegative time.
SetCoreLoadhas data[timestamp, coreIndex, watts]. Queue a load change for the indexed core without advancing temperatures. Only the last queued change for a core is retained.Tickhas data[timestamp]. First settle temperatures and shutdowns. Then apply the pending loads. A pending load restarts a shut-down core only if its just-observed temperature is strictly below50. Restarting preserves that temperature. A failed restart leaves the core shut down and discards the pending change.- Pending changes applied to a running core replace its load. Clear all pending changes after this phase.
Choosing active cooling
At every tick, recompute active cooling from scratch for running cores. Turn it on for every core with temperature strictly above 60. Also turn it on for every unengaged core whose resulting rise rate would be strictly above 0.5 degrees per second. Engaging cores reduces passive capacity through the Fibonacci penalty, which can force more cores to engage during the same tick.
Use the smallest closed engagement set: begin with the temperature-forced cores, recompute passive cooling, add all unengaged cores whose net heat without active cooling exceeds 25 watts, and repeat until no new core qualifies. A core already selected stays selected during this decision, even if its active cooling reduces its final rise rate. Shut-down cores never engage.
Change reports
After the tick is complete, compare each core's final status with its status after the previous tick; initially every status is idle. Return one row containing exactly the changed cores as coreId=status strings in lexicographic core-ID order. A core that shuts down and restarts within one tick is reported only if its final status differs. Return an empty row when no final status changes.
Return one row per Tick in call order. coreIndex is the zero-based index in coreIds, and activeCooling is aligned with that array. Complete simulateOverheatController.
Function
simulateOverheatController(pooledCooling: double, coreIds: String[], activeCooling: double[], operations: String[], operationData: double[][]) → String[][]Examples
Example 1
pooledCooling = 0coreIds = ["a"]activeCooling = [100]operations = ["SetCoreLoad","Tick","Tick","SetCoreLoad","Tick"]operationData = [[0,0,30],[1],[101],[102,0,0],[103]]return = [["a=cooling"],[],["a=idle"]]The first tick applies load 30 after settling the initial zero-load interval. With no passive cooling, the unengaged rise rate is 0.6, so the core engages. Active cooling keeps the temperature at the ambient floor. The last pending load is 0, so the final tick turns active cooling off.
Example 2
pooledCooling = 1000coreIds = ["z"]activeCooling = [0]operations = ["SetCoreLoad","Tick","Tick","SetCoreLoad","Tick"]operationData = [[0,0,2000],[1],[4],[1000,0,0],[1001]]return = [["z=cooling"],["z=shutdown"],["z=idle"]]At time 1, load 2000 forces engagement. The effective passive capacity for the next interval is 900, giving a rise rate of 22 degrees per second. At time 4, the observed temperature is 86 and the core shuts down. With load cleared and active cooling off, passive cooling lowers its temperature by 0.04 degrees per second. At time 1001 it is below 50, so the queued zero load restarts it.
Constraints
1 <= coreIds.length = activeCooling.length <= 200.- Core IDs are distinct nonempty ASCII strings containing only letters, digits, underscores and hyphens.
0 <= pooledCooling, activeCooling[i], watts <= 10^4.1 <= operations.length = operationData.length <= 2000andcoreIds.length * operations.length <= 2 * 10^5.- Every operation is
SetCoreLoadorTick, with a correctly shaped data row and valid core index. - Timestamps are strictly increasing integers in
[0, 10^4]. - There is at least one
Tick. - Use double-precision arithmetic. Compare temperature thresholds in degrees and the rise-rate trigger as a net-heat threshold of
25watts. A compared value within10^-7of its threshold, in those units, is treated as equal before applying the strict or inclusive rule. Every comparison is either mathematically equal or separated from the threshold by at least10^-6.