Optimization in Dynamic Environments

"A static problem asks you to find the answer. A dynamic one asks you to keep having one."- Claude 2026

Optimization in Dynamic Environments

Almost every optimization method is introduced on a problem that sits perfectly still: a fixed objective, fixed constraints, one best answer waiting to be found. Real problems move while you are solving them. Demand shifts, a machine fails, prices update, the data your model was fitted on stops describing the world. The goal quietly changes from finding an optimum to keeping one — and that change of goal invalidates a surprising amount of standard practice.

Optimization means searching a space of possible answers for the one that scores best under some measure: the objective, a single number to be pushed up or down, subject to constraints that a legal answer must satisfy.

Plasma inside the TCV tokamak being shaped and held in place by a learned controller.
An environment that will not wait: plasma inside a tokamak is unstable on timescales of milliseconds, so its controller has to decide, act, observe the result and decide again, continuously. A learned controller shaping and stabilising the plasma in the Swiss Plasma Center's TCV reactor. Source: Google DeepMind, "Accelerating fusion science through learned plasma control."

Learning objectives

By the end of this page you should be able to:

  1. Explain the challenges of optimization in dynamic and uncertain environments.
  2. Apply AI-driven methods for real-time optimization under changing conditions.
  3. Assess the adaptability of optimization algorithms in evolving systems.

When the Problem Moves

Picture the set of all possible answers as a landscape where height is quality, and optimization as the search for the highest point. In a static problem that landscape is a photograph. In a dynamic problem it is a video: peaks rise and fall, the tallest one moves, and sometimes a region that was legal to stand in becomes off-limits.

Three snapshots of a landscape of solution quality. A cluster of candidate solutions converges on the tallest peak; the landscape then shifts, and by the third snapshot the tallest peak is elsewhere while the cluster remains where the old peak was.
The core difficulty in one picture. A search that succeeds — everything collected on the best peak — is precisely a search that has thrown away its ability to notice a better peak appearing somewhere else. In a moving landscape, convergence is not the finish line; it is the failure mode.

Four different things can move, and they demand different responses, so it is worth separating them before choosing a method:

The objective. What counts as good changes — electricity prices move, a delay becomes more costly at 5 p.m. than at noon. The same answer scores differently tomorrow.
The constraints. A vehicle breaks down, a supplier goes offline, a runway closes. Answers that were legal become illegal, and the plan in force may already be infeasible.
The problem itself. New orders arrive, jobs finish, customers cancel. The set of things being decided grows and shrinks while you decide about it.
The model. Nothing visible changes, but the statistical relationship a forecast was fitted on does — the phenomenon known as concept drift. The optimizer keeps solving the problem correctly, using inputs that are quietly wrong.

How the change arrives matters as much as what changes. Four shapes recur across the literature, and each suggests a different response:

Four small time-series panels showing abrupt change, gradual change, incremental drift and recurring change.
Abrupt change rewards fast detection and a restart; gradual change tends to defeat detectors that look for a single break point; incremental drift rewards continuous tracking rather than any notion of "the change"; recurring change rewards memory — storing good old solutions and testing them again when conditions look familiar, which is far cheaper than rediscovering them.

Beyond shape, three properties of the change decide almost every design choice you will make:

PropertyThe questionWhat it decides
FrequencyHow often does the world change relative to how long a solve takes?Whether you can afford to re-optimize at all, or must run a policy that answers instantly
SeverityHow far does the optimum move when it moves?Whether to repair the current solution or start over; small moves reward warm starts, large ones do not
PredictabilityIs the change forecastable, cyclic, or random?Whether to anticipate (forecast and pre-position) or merely to react
VisibilityDo you get told that something changed?Whether you need explicit change detection or can simply keep learning continuously
ReversibilityCan you undo a committed decision?How much of the plan to commit to now versus keep open — the value of hedging

One consequence deserves stating plainly, because it inverts a habit built up on static problems. On a fixed landscape, a population of candidate solutions collapsing onto one answer is success. On a moving landscape it is the loss of the only asset that lets you notice the world has moved. The same is true of a forecasting model that has fit its training data perfectly, and of a solver whose answer is optimal for a snapshot that expired an hour ago.

Methods for Optimizing in Real Time

The practical toolkit divides into five strategies. Most production systems combine several, and the choice between them follows directly from the properties in the table above.

1. Detect and repair. Notice the change, then fix the incumbent solution rather than rebuilding it.
2. Stay ready. Deliberately keep diversity so the search can react at all.
3. Predict and re-plan. Optimize over a horizon, commit to the first step only, repeat.
4. Learn online. Update a policy continuously from the outcomes it produces.
5. Be robust instead. When re-optimizing is impossible, choose a plan that survives many futures.

1. Detect the change, then repair rather than restart

If change arrives as discrete events, the first job is noticing. Two mechanisms do this cheaply. Sentinel solutions are a handful of candidates whose scores are re-evaluated every cycle: if a score changes without the candidate changing, the environment did. Statistical drift detectors watch a stream of errors or rewards and signal when its distribution shifts — ADWIN maintains an adaptive window over recent observations and cuts it whenever two sub-windows disagree enough to be unlikely by chance.

Once a change is detected, restarting from scratch is almost always the wrong move. A change of moderate severity leaves most of the previous answer still good, so the efficient response is a warm start: keep the incumbent, repair the parts the change invalidated, and re-optimize locally around it. This is the same destroy-and-repair idea that powers large neighborhood search, applied to time rather than to problem size.

2. Keep diversity on purpose

Population methods such as genetic algorithms and swarm methods lose their ability to react as they converge. Three standard repairs exist, and they can be combined:

  • Random immigrants. Replace part of the population with fresh random candidates every generation, or after every detected change, guaranteeing a permanent supply of unexplored ground.
  • Hypermutation. Temporarily raise the mutation rate immediately after a change, spraying the population outward, then return it to normal so the search can settle again.
  • Multiple populations and memory. Keep sub-populations on different peaks so a rising peak is already occupied when it becomes best, and store good solutions from past environments to re-test when conditions recur.

The effect is easy to measure. Below, five peaks drift every twenty generations; the same genetic algorithm runs with and without random immigrants plus a short burst of hypermutation after each change. The score reported is tracking error — how far the best solution found since the last change falls short of the true optimum, averaged over every generation:

import math
import random

random.seed(3)
span, dim, n_peaks = 50.0, 2, 5
peaks = [[random.uniform(0, span) for _ in range(dim)] for _ in range(n_peaks)]
heights = [random.uniform(40, 70) for _ in range(n_peaks)]

def score(x):
    return max(h - 0.8 * math.dist(x, c) for c, h in zip(peaks, heights))

def shift(severity=6.0):
    for c in peaks:
        for i in range(dim):
            c[i] = min(span, max(0.0, c[i] + random.gauss(0, severity)))

def random_point():
    return [random.uniform(0, span) for _ in range(dim)]

def run(adaptive, generations=300, interval=20, size=30):
    random.seed(11)
    pop = [random_point() for _ in range(size)]
    trace, best_since_change, age = [], None, 0
    for g in range(generations):
        if g and g % interval == 0:
            shift()
            best_since_change, age = None, 0
            if adaptive:
                pop[size // 2:] = [random_point() for _ in range(size - size // 2)]
        sigma = 6.0 if adaptive and age < 3 else 1.0
        pop.sort(key=score, reverse=True)
        best = score(pop[0])
        best_since_change = best if best_since_change is None else max(best_since_change, best)
        trace.append(max(heights) - best_since_change)
        parents = pop[:size // 3]
        pop = [p[:] for p in parents]
        while len(pop) < size:
            a, b = random.sample(parents, 2)
            child = [(u + v) / 2 + random.gauss(0, sigma) for u, v in zip(a, b)]
            pop.append([min(span, max(0.0, v)) for v in child])
        age += 1
    return trace

converged = run(adaptive=False)
adaptive = run(adaptive=True)
print('converged GA', round(sum(converged) / len(converged), 2))
print('adaptive GA ', round(sum(adaptive) / len(adaptive), 2))

The converged run averages a tracking error of 1.33; the adaptive one, 0.43 — the same algorithm, the same budget, three times closer to the moving optimum. Plotting the error generation by generation shows why, and it is not that the adaptive run is generally better:

Tracking error over 300 generations for both runs. Both spike at each environment change, but the converged algorithm spikes far higher and decays slowly, while the adaptive one spikes less and returns to near zero within a few generations.
Between changes both algorithms sit at essentially zero error. The entire difference lives in the moments after a change: the converged population takes most of the interval to crawl back, while the adaptive one recovers within a few generations. Recovery time, not final quality, is what separates them.

The advantage also grows with severity, which is the honest way to report this kind of result — a single number hides the fact that diversity mechanisms cost you nothing much when changes are tiny and save you everything when they are large:

Change severityConverged GAAdaptive GARatio
61.330.433.1×
102.690.525.2×
154.720.598.0×

3. Predict, commit once, re-plan

Where a forecast exists, the dominant industrial pattern is model predictive control (MPC), also called receding-horizon control. At each step, use a model to predict how the system will evolve, optimize a whole sequence of decisions over that horizon, then throw away all but the first decision, take a fresh measurement, and solve again.

Three rows showing a planning window sliding forward one step at a time; in each row only the first action of the plan is applied and the rest is dashed.
Receding-horizon control. Planning far ahead makes the immediate decision a good one; committing only to the first step means every subsequent decision is made with information that did not exist when the plan was drawn. Discarding most of the plan is not waste — it is the mechanism.

MPC is how a building pre-cools before a hot afternoon, how a battery decides when to charge against a price forecast, and how a chemical plant holds a setpoint through disturbances. It also inherits the weakness of its model: when the forecast is biased, the plan is confidently wrong, which is why MPC is usually paired with feedback that corrects the model as measurements arrive.

4. Learn online — and forget on purpose

When no usable model of the environment exists, the alternative is to learn a decision rule directly from outcomes. In a changing world the natural measure of success is not "did we find the optimum" but regret: how much worse did the decisions we actually made do, compared with the best decisions available in hindsight? Regret is defined over a sequence, which is exactly the right shape for a problem that never ends.

The smallest instructive case is the multi-armed bandit: several options with unknown payoffs, one choice per round, and only the chosen option's payoff observed. The non-stationary version adds the twist that the payoffs drift over time. There, the classic estimator — average all rewards ever seen for each option — becomes actively harmful, because every stale observation gets equal weight forever. Replacing it with a constant step size makes the estimate an exponentially weighted average of recent rewards, so old evidence decays away:

import numpy as np
rng = np.random.default_rng(0)

arms, steps, runs, epsilon = 10, 10000, 50, 0.1

def testbed(alpha=None):
    reward = optimal = 0
    for _ in range(runs):
        true_value = np.zeros(arms)
        estimate, count = np.zeros(arms), np.zeros(arms)
        for _ in range(steps):
            a = rng.integers(arms) if rng.random() < epsilon else int(estimate.argmax())
            r = rng.normal(true_value[a], 1.0)
            count[a] += 1
            estimate[a] += (alpha or 1 / count[a]) * (r - estimate[a])
            reward += r
            optimal += a == int(true_value.argmax())
            true_value += rng.normal(0, 0.01, arms)
    total = runs * steps
    return reward / total, 100 * optimal / total

for name, alpha in (('sample average', None), ('constant step ', 0.1)):
    r, pct = testbed(alpha)
    print(f'{name}  reward {r:5.2f}  optimal {pct:4.1f}%')

The averaging rule earns 0.69 per step and picks the genuinely best option 43.9% of the time; the forgetting rule earns 0.91 and picks it 67.1% of the time. Nothing about the search changed — only how much the past is allowed to count. Every method in this section is, in some form, a decision about that.

With context. Contextual bandits condition the choice on features of the current situation, which is how recommendation, pricing and ad systems handle preferences that shift under them.
With consequences. When today's action changes tomorrow's situation, the problem is reinforcement learning; deep RL methods extend it to large state spaces, at the price of needing far more experience.

5. When you cannot react, be robust

Some decisions are committed before the uncertainty resolves and cannot be revised: where to build the depot, which contracts to sign, what to load on the truck before it leaves. Here the answer is not a faster loop but a different objective. Robust optimization asks for the plan whose worst case across a set of plausible futures is best; stochastic optimization asks for the plan with the best expected outcome across those futures. Both deliberately give up peak performance on the future that actually happens, in exchange for not collapsing on the ones that might.

The same idea appears in learned controllers as domain randomization: train across many randomized variations of the environment so the resulting policy does not depend on any one of them being accurate.

The constraints that only exist in real time

Three requirements have no equivalent in static optimization, and they routinely decide which method is usable:

A decision deadline. An answer that arrives after the moment has passed scores zero, however good it is. The budget is wall-clock time, not iterations.
Anytime behavior. The method must hold a usable answer at every instant and improve it if given more time, because it can be interrupted at any point.
Solution stability. A plan that churns completely each cycle is unusable even when it scores better — drivers, operators and downstream systems have already acted on the last one. Churn belongs in the objective, as a penalty for deviating from the plan in force.

Assessing Adaptability

The standard report for a static optimizer — the quality of the final answer — is meaningless here, because there is no final answer. A dynamic optimizer is judged on a whole trajectory, and the useful measures capture different failures:

MeasureWhat it isThe failure it catches
Tracking (offline) errorAverage gap to the true optimum over every time stepSustained mediocrity, including between changes
Recovery timeSteps needed to return within a threshold of the optimum after a changeA method that is excellent when settled and helpless when disturbed
RegretCumulative shortfall against the best decisions in hindsightSlow learning and over-exploration, on problems with no defined "optimum"
Worst-case errorThe largest gap reached at any pointRare but unacceptable excursions hidden by a good average
Stability / churnHow much the solution changes per cycleA plan too volatile to execute in the real world
Cost of adaptationCompute, data and evaluations spent per changeAdaptivity bought at a price exceeding the loss it avoids

Because these must be measured against a known moving target, the field relies on generators rather than fixed instances. The Moving Peaks Benchmark — the setting the code in §2 imitates — generates a landscape whose peaks shift in position, height and width at a controlled frequency and severity, so the optimum is known at every instant. Dynamic variants of routing and scheduling problems add customers or machine failures mid-solve, and drifting data streams do the same for learned components.

Interrogating an adaptive-optimization claim

Tested across a range of change? Results at one frequency and one severity say almost nothing. The interesting question is where the method's advantage appears and where it disappears.
Was the change announced? Many published methods are told when the environment changed. Real systems are not, and detection is often the hard part.
Compared on equal wall-clock time? Per-iteration comparisons flatter expensive methods, which is fatal in a setting defined by deadlines.
Does the baseline get to restart? "Adaptive beats static" is unimpressive if the static method was never allowed to simply re-solve from scratch — often a strong and much simpler baseline.

One more caution, familiar from every applied setting: a method tuned on a particular drift pattern has, in effect, been told what will happen. If the tuning set contains only gradual drift, expect the method to fail on the abrupt change that eventually arrives — the dynamic-environment version of overfitting.

Two Systems That Cannot Pause

Controlling a fusion plasma. The image at the top of this page shows plasma inside the Tokamak à Configuration Variable at EPFL's Swiss Plasma Center. Plasma is held in place by magnetic fields produced by control coils, and it is unstable: the state evolves continuously and a wrong command is unrecoverable within milliseconds. Conventional practice engineers a separate controller for each desired plasma shape, a slow and specialised process. Researchers instead trained a reinforcement learning agent in simulation to map measurements directly to coil voltages, then deployed the trained network inside the tokamak's real-time control loop, where it produced and held a range of plasma configurations — including elongated shapes and a configuration with two separate plasmas held simultaneously (Degrave et al., Nature, 2022). It is the clearest demonstration that a learned policy can meet a hard real-time deadline in a genuinely unforgiving environment — and also a clear illustration of the cost: the simulator, the safety analysis, and the engineering around the policy dwarf the policy itself.

Retiming traffic signals from observed traffic. Traffic is dynamic on every timescale — hour, day, season, roadworks — while signal timing plans are typically set once and left for years. Google's Project Green Light models intersections from aggregated Maps driving trends, identifies where the timing no longer matches the traffic, and hands city engineers recommendations they can implement on existing hardware.

An urban intersection with traffic signals, illustrating AI-assisted retiming of signal plans.
Retiming signals rather than rebuilding intersections: the project reports operating in more than 100 cities, affecting on the order of 47 million car rides a month, with potential reductions of up to 30% in stops and 10% in greenhouse gas emissions at optimized intersections. Source: Google Research, Project Green Light.

The two sit at opposite ends of a spectrum worth noticing. The plasma controller closes the loop in milliseconds with no human in it; Green Light closes the loop in weeks with a city engineer in the middle, and gets its adaptivity from re-solving as observations accumulate rather than from any online algorithm. Both are optimization in a dynamic environment. The difference is only how fast the environment moves relative to how fast a decision can be made and acted on — which is, in the end, the single number that organizes this whole subject.

Tools & Tutorials

  • River — concept drift detection — a short, runnable walkthrough that generates a drifting stream and detects the change points with ADWIN; the rest of the library is built for models that learn one observation at a time.
  • do-mpc — an open-source Python toolbox for model predictive control and moving-horizon estimation, with getting-started tutorials and a gallery of worked closed-loop examples including robust multi-stage MPC.
  • Vowpal Wabbit — contextual bandit content personalization — a notebook-style tutorial that simulates a recommender and then swaps the reward function halfway through, so you can watch a learner recover from a change of preferences.
  • Eclipse SUMO — TraCI traffic light tutorial — control signals from a Python script that reads live detector state inside a running traffic simulation: a small, complete closed loop you can modify.
  • EDOLAB — an open-source MATLAB platform bundling 25 dynamic-optimization algorithms and three benchmark generators (including the Moving Peaks Benchmark), with animated visualisation of how the landscape changes between environments.

Further reading

→ This page was created with help from Claude AI.