FastPrepOverheat Prevention Controller

Overheat Prevention Controller

Optiver logoOptiver● HardINTERNNEW GRADOA
Learn

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 temperature 20, load 0, and active cooling off. A running core is idle when active cooling is off and cooling when it is on.
  • Each core has a passive-cooling demand of load + 2 watts. A shut-down core has load 0 and still receives passive cooling.
  • Let k be the number of cores with active cooling on. Let F[1], F[2], ... = 1, 2, 3, 5, .... Effective shared passive capacity is pooledCooling * (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 i receives effectiveCapacity * demand[i] / totalDemand.
  • An actively cooled core receives exactly activeCooling[i] additional watts of cooling.
  • Temperature changes at 0.02 degrees per second per watt of net heat, where net heat is load - passiveCooling - activeCoolingIfOn. Temperature cannot fall below 20.
  • 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 to 80.

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.

  • SetCoreLoad has 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.
  • Tick has 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 below 50. 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 <= 2000 and coreIds.length * operations.length <= 2 * 10^5.
  • Every operation is SetCoreLoad or Tick, 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 25 watts. A compared value within 10^-7 of 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 least 10^-6.

More Optiver problems

See Optiver hiring insights
public String[][] simulateOverheatController(double pooledCooling, String[] coreIds, double[] activeCooling, String[] operations, double[][] operationData) {
    // Write your code here.
}
pooledCooling0
coreIds["a"]
activeCooling[100]
operations["SetCoreLoad","Tick","Tick","SetCoreLoad","Tick"]
operationData[[0,0,30],[1],[101],[102,0,0],[103]]
expected[["a=cooling"], [], ["a=idle"]]
Checking account…