Two parameters

How long a reweighting stays true

Johnson's one Bellman–Ford run costs under one per cent of an all-pairs computation because it is divided over every source. Asked one query at a time it is divided over nothing, and it still repays itself after 2.7 queries — because the preparation is one Bellman–Ford and every query saves a third of another. What decides the trade is not the query count but whether the graph holds still: at half a per cent of arcs redrawn between queries the stored potential is worth exactly nothing, and its life is geometric at a per-arc failure rate of 6.6%.

One Bellman–Ford buys every Dijkstra priced three ways of computing all-pairs shortest paths on a graph with negative arcs, and found Johnson’s method cheapest over a wide band of densities. Its reweighting — one Bellman–Ford run from a virtual source joined to every vertex at cost zero, whose distances become a potential that makes every arc’s repriced cost non-negative — came to under one per cent of the total, because it is paid once and then divided over 256 Dijkstra runs.

A system answering queries as they arrive divides it over nothing. The first query pays for the whole preparation and gets one shortest-path tree for it; the second query gets the preparation free. So the question that essay left is a break-even: how many single-source queries have to arrive before paying in advance is cheaper than not.

This page answers it, and the answer is smaller than expected — which makes the interesting question the second one. A potential is a statement about the arcs as they were. This page measures how long that statement stays true.

Two queries and a bit

The setting is the one the all-pairs page used: a directed graph of 256 vertices whose arcs cost one to nine plus the difference of a fixed random potential, so that a third of them are negative and no cycle is. Queries name a source; the answer is that source’s distances to every vertex, and every answer is compared entry by entry against the other method’s.

One Bellman–Ford bought in advance is repaid by query 2.7, because the preparation is one Bellman–Ford and every query saves 32% of anotherCumulative counted work against the number of single-source queries answered, on a 256-vertex directed graph of 2,009 arcs with 736 of them negative and no negative cycle. Bellman–Ford from each query's source costs 11,787 a query from nothing; one reweighting costs 10,045 and then Dijkstra on the reduced costs costs 8,069 a query. The two lines cross at 2.70 queries, marked. Every query's answers are compared entry by entry.0396,049792,0981,188,1481,584,1970326496128queries answeredcounted work, cumulativebreak-even at 2.7 queriesBellman–Ford from each sourceone reweighting, then Dijkstra256 vertices, 2,009 arcsanswers compared entry by entry
Fig. 1 Cumulative counted work — relaxation attempts plus priority-queue comparisons — against the number of single-source queries answered on a 256-vertex graph of 2,009 arcs, 736 of them negative. Bellman–Ford from each query’s source costs 11,787 a query from nothing. One reweighting costs 10,045 and then Dijkstra on the repriced arcs costs 8,069 a query. The two lines cross at 2.70 queries, marked.

The preparation is repaid before the third query. That is not a surprising number once it is stated the right way round: the reweighting is one Bellman–Ford run, so it costs about what one query would have cost, and it has to be repaid out of the saving on each later query. The saving is 32% — Dijkstra on repriced arcs costs 8,069 against Bellman–Ford’s 11,787 — so about three queries’ worth of saving covers one query’s worth of preparation.

Bellman–Ford's passes per source fall from 8.1 to 3.6 as the graph fills in, and the reweighting stays under 2% of Johnson's workOn directed graphs of 128 vertices with negative arcs and no negative cycle, the mean number of passes Bellman–Ford makes from each source before a pass changes nothing, and the share of Johnson's counted work spent on its one Bellman–Ford run from the virtual source. Out-degree 2: 99 of 254 arcs negative; 8.09 passes; reweighting 1.28% of Johnson's 128,985. Out-degree 4: 182 of 502 arcs negative; 6.04 passes; reweighting 0.84% of Johnson's 316,102. Out-degree 8: 378 of 991 arcs negative; 5.14 passes; reweighting 0.78% of Johnson's 446,857. Out-degree 16: 724 of 1,914 arcs negative; 4.58 passes; reweighting 1.26% of Johnson's 660,464. Out-degree 32: 1,367 of 3,605 arcs negative; 4.18 passes; reweighting 1.62% of Johnson's 927,285. Out-degree 64: 2,411 of 6,429 arcs negative; 3.62 passes; reweighting 1.49% of Johnson's 1,327,173.2481632641average out-degreepasses per source · reweighting share, %Bellman–Ford passesreweighting, % of Johnson128 vertices, costs 1–9 plus a potentialno negative cycle by construction
Fig. 2 The same construction at 128 vertices, in the setting the break-even is being contrasted with: Bellman–Ford’s mean passes per source as the graph fills in, and the reweighting’s share of Johnson’s total work when it is divided over every source. The share stays under a couple of per cent at every density, which is what “under one per cent of its work” meant, and the passes fall as the graph fills because a denser graph reaches its distances in fewer rounds of relaxation.

The contrast between that plate and the one above it is the whole of the reframing. Divided over 128 sources the preparation is a rounding error and the only question is which method is asymptotically better. Divided over one source it is a whole query, and the question becomes when the second query arrives — which, as the next plate shows, is almost immediately, so the framing that put the preparation at the centre was answering a question nobody has.

Both halves of that arithmetic are worth attention. The preparation is cheap because Bellman–Ford from a virtual source joined to everything converges in very few passes: every vertex is at distance at most zero immediately, so the pass count is set by the longest chain of improvements rather than by the diameter. The saving per query is only 32% because Bellman–Ford on this graph is not paying its worst case either — its early exit stops it after a handful of passes, so the classical factor of VV between the two methods does not appear.

The break-even does not move much with density

A break-even of three queries would be a different kind of finding if it were three at one density and three hundred at another.

The one reweighting pays for itself after 1.2, 2.3, 3.1, 1.6, 1.7, 1.4 queries at out-degrees 2, 4, 8, 16, 32, 64 — never more than a handfulThe number of single-source queries after which paying for one Bellman–Ford reweighting and answering with Dijkstra costs less than running Bellman–Ford from each source, against average out-degree, on 256-vertex directed graphs whose arcs cost one to nine plus the difference of a random potential. Out-degree 2: reweighting 2,535, Bellman–Ford 4,674 a query, Dijkstra 2,541, break-even 1.19. Out-degree 4: reweighting 4,036, Bellman–Ford 7,221 a query, Dijkstra 5,447, break-even 2.27. Out-degree 8: reweighting 10,045, Bellman–Ford 11,363 a query, Dijkstra 8,096, break-even 3.07. Out-degree 16: reweighting 15,832, Bellman–Ford 21,398 a query, Dijkstra 11,542, break-even 1.61. Out-degree 32: reweighting 30,664, Bellman–Ford 34,018 a query, Dijkstra 16,032, break-even 1.70. Out-degree 64: reweighting 43,290, Bellman–Ford 54,113 a query, Dijkstra 23,404, break-even 1.41.2481632641average out-degreequeries before the reweighting paysqueries to break even256 vertices, static graphthe reweighting is one Bellman–Ford
Fig. 3 The number of single-source queries after which one reweighting plus Dijkstra has cost less than Bellman–Ford from each source, against average out-degree, on logarithmic axes: 1.19 at out-degree 2, 2.27 at 4, 3.07 at 8, 1.61 at 16, 1.70 at 32 and 1.41 at 64. The reweighting costs 2,535 at the sparsest and 43,290 at the densest; both methods grow with it.

It does not move much. Across a factor of thirty-two in density the break-even stays between one and four queries, and it is not monotone — the sparse end is cheapest because Bellman–Ford’s early exit fires latest there, and the dense end is cheap because Dijkstra’s advantage is largest there. Nothing on that plate would change a design decision. A system that expects more than about five queries in the lifetime of its graph should store the potential, at any density drawn.

That makes the query count the wrong parameter, and it is worth saying why explicitly. The all-pairs page’s framing — preparation divided over many uses — suggests a trade that becomes better the more uses there are, and it is one; but the preparation here is a single run of the same algorithm the queries would otherwise use, so it can never be more than a few queries’ worth. Preparation that dominates is preparation that computes something the queries could not, and the structure paid for before the first query is about the case where it does. Johnson’s reweighting is not that case.

What is actually at stake: the graph moving

A potential is valid for a set of arc costs. If an arc’s cost falls, its repriced cost can go negative, and Dijkstra on repriced arcs stops being correct — not slightly wrong, but wrong in the way the adversary who hides the edge describes, settling a vertex before the route that would have improved it is found.

So the measurement that matters is not how many queries arrive but how much changes between them. Here a stated share of arcs have their costs redrawn between queries, from the same construction — one to nine plus the fixed potential’s difference — so no cycle can go negative and the question stays answerable. Before each query the stored potential is checked against every arc, and recomputed if any repriced cost is negative.

A stored reweighting is 31% cheaper on a graph that never changes and loses at about 0.5% of arcs redrawn between queriesTotal counted work of 128 single-source queries answered from a stored potential — Bellman–Ford once, Dijkstra thereafter, and the potential recomputed whenever an update leaves some repriced arc negative — divided by the work of running Bellman–Ford from every query's source, against the share of the 2,009 arcs whose cost is redrawn between queries. One is the line where the two cost the same. 0.00%: ratio 0.691, 1 reweightings, a potential surviving every query. 0.02%: ratio 0.731, 4 reweightings, a potential surviving 41.00 queries. 0.05%: ratio 0.753, 9 reweightings, a potential surviving 14.00 queries. 0.10%: ratio 0.803, 16 reweightings, a potential surviving 6.87 queries. 0.20%: ratio 0.887, 30 reweightings, a potential surviving 3.21 queries. 0.50%: ratio 1.015, 62 reweightings, a potential surviving 1.08 queries. 1.00%: ratio 1.218, 95 reweightings, a potential surviving 0.35 queries. 2.00%: ratio 1.433, 122 reweightings, a potential surviving 0.06 queries.0.500.751.001.251.5000.02%0.05%0.10%0.20%0.50%1.00%2.00%arcs redrawn between queriesstored ÷ Bellman–Ford per querystored potentialBellman–Ford per query256 vertices, 128 queriesrecomputed whenever an arc goes negative
Fig. 4 Total counted work of 128 queries answered from a stored potential, divided by the work of Bellman–Ford from every query’s source, against the share of the 2,009 arcs redrawn between queries. At no churn the stored potential costs 0.691 of the alternative. At 0.02% of arcs it costs 0.731 and is recomputed 4 times; at 0.1%, 0.803 and 16 times; at 0.5%, 1.015 and 62 times; at 2%, 1.433 and 122 times. One — where the two cost the same — falls at about half a per cent.

Half a per cent of arcs is ten arcs out of two thousand. That is the whole margin: a graph in which ten arc costs change between one query and the next is a graph on which the reweighting is worth nothing, and one in which forty change is a graph on which storing it costs 43% more than not bothering.

The shape of that curve is not the usual diminishing one. It rises through one and keeps rising, because a potential that is recomputed on most queries is paying for a Bellman–Ford run and a Dijkstra run per query where the simple method pays for one Bellman–Ford. Past the crossing the stored potential is not merely useless; it is the more expensive method by construction, and its cost tends to the sum of both rather than to either.

A potential’s life, and the rate that sets it

The recomputation count is a consequence of something simpler, which can be measured on its own: how likely one arc’s redraw is to break the potential.

A potential's life is geometric in how many arcs move at once, at a per-arc failure rate of about 6.6% — and the account understates it by a third when only one arc movesMean number of queries a stored potential survives before some repriced arc goes negative, against the number of arcs redrawn between queries, on logarithmic axes, over 1,024 queries on a 256-vertex graph of 2,009 arcs. The second line is the prediction from a per-arc failure rate measured separately: an update breaks the potential with probability one minus that rate's complement raised to the number of arcs it touches, and a geometric life follows. 1.0 arcs an update: survives 19.86 queries against a predicted 13.52, over 49 recomputations, per-arc rate 6.86%. 2.0 arcs an update: survives 8.73 queries against a predicted 6.34, over 105 recomputations, per-arc rate 7.04%. 4.0 arcs an update: survives 3.42 queries against a predicted 3.18, over 231 recomputations, per-arc rate 6.57%. 10.0 arcs an update: survives 1.16 queries against a predicted 1.06, over 473 recomputations, per-arc rate 6.39%. 20.1 arcs an update: survives 0.40 queries against a predicted 0.33, over 730 recomputations, per-arc rate 6.66%. 40.2 arcs an update: survives 0.07 queries against a predicted 0.08, over 959 recomputations, per-arc rate 6.27%.1241020400.1110arcs redrawn between queriesqueries a potential survives, meanmeasuredgeometric account256 vertices, 1,024 queriesper-arc rate measured, not fitted
Fig. 5 Mean queries a stored potential survives before some repriced arc goes negative, against how many arcs are redrawn between queries, on logarithmic axes, over 1,024 queries. Measured: 19.86 queries when one arc moves, 8.73 at two, 3.42 at four, 1.16 at ten, 0.40 at twenty, 0.07 at forty. The second line is a geometric account built from a separately measured per-arc failure rate of about 6.6%.

The per-arc rate is the quantity with an explanation. For each arc, counting how many of its nine possible redrawn costs would leave it negative under the potential in force gives 6.3% to 7.0% across every churn rate measured — the same number whether one arc moves or forty. It is a property of how tight the potential is against these arcs, not of the update process, and once it is known the rest follows: an update touching kk arcs breaks the potential with probability 1(1q)k1 - (1-q)^k, and the number of queries between recomputations is geometric with that parameter.

The account is right where several arcs move at once — 3.42 against a predicted 3.18 at four arcs, 1.16 against 1.06 at ten, 0.07 against 0.08 at forty — and it understates the potential’s life by about a third when one arc moves, predicting 13.5 where 19.9 is measured. The likeliest reason is an assumption the account makes and the process does not honour: it treats every redraw as independent of every other, while an arc redrawn twice between recomputations has its second redraw measured against a cost the potential has already survived. At forty arcs an update that hardly matters, because almost every update breaks the potential anyway; at one arc an update, over a life of twenty queries, twenty of the two thousand arcs have moved and a repeat is not rare. The account is reported as it stands rather than fitted, because a fitted constant would hide exactly this.

Where the 6.6% comes from

The rate is not a fitted constant. It can be read off the potential’s own slack.

The reweighting leaves 277 of 2,009 arcs at exactly zero slack, and a redraw only breaks the potential when it falls further than the slack it lands onHow many of the 2,009 repriced arc costs take each value, on a 256-vertex graph whose raw costs run from one to nine plus the difference of a potential. An arc's repriced cost is its slack: a redraw breaks the potential only if the new cost is lower than the old one by more than that. 0: 277, 1: 120, 2: 155, 3: 175, 4: 202, 5: 215, 6: 192, 7: 158, 8: 167, 9: 116, 10: 91, 11: 46, 12: 44; above 12: 51. The 277 arcs at zero are the ones on shortest paths from the virtual source, and every one of them is broken by any redraw at all that lowers it.0139277012345678910111213+repriced cost — the arc's slackarcs256 vertices, 2,009 arcsdark: zero slack, broken by any fall
Fig. 6 How many of the 2,009 repriced arc costs take each value, on the 256-vertex graph. The repriced cost is the arc’s slack: 277 arcs sit at exactly zero, 120 at one, and the distribution runs out past twelve with 51 arcs above it. The 277 at zero are the arcs on shortest paths from the virtual source, and any redraw that lowers such an arc at all breaks the potential.

A redraw replaces an arc’s raw cost, one to nine, with another drawn the same way, and the repriced cost moves by exactly the difference. So an arc currently costing cc with slack ss is broken by any of the redraws below csc - s, which is cs1c - s - 1 of the nine when that is positive and none of them otherwise. Averaging that over the arcs gives the 6.6% the survival plate uses, and the two largest contributions are visible in the histogram: the 277 arcs at zero slack, which lose on any fall — about four of nine redraws on average — and the 120 at slack one, which lose on about three.

That is also why the rate is a property of the graph rather than of the traffic. The 277 arcs at zero slack are not an accident of this construction; a potential computed by Bellman–Ford from a virtual source is tight, meaning every vertex’s value is achieved by some path, and the arcs on those paths necessarily reprice to zero. There are at least V1V - 1 of them on any connected graph, so a reweighting’s fragility has a floor: at least one arc in every VV is broken by any fall at all, whatever the costs.

Whether an update has to be believed

There is a cheaper policy hiding in the check. The potential is recomputed when some repriced arc is negative, and the check that discovers this is a pass over every arc — which costs about a fifth of a Bellman–Ford pass and is already counted above. But an update that raises an arc’s cost cannot break anything, since raising ww raises w+h(u)h(v)w + h(u) - h(v). Only a fall can, and only a fall past the arc’s current slack.

That gives a system a test it can apply per update rather than per query: when an arc’s cost changes, compare the new repriced cost with zero, and mark the potential invalid only if it is negative. It is one subtraction against a full scan, and it is exactly the 6.6% event measured above. Nothing on this page prices the two checks against each other, because the scan is the cheaper part of the recomputation it guards; the point is that the rate the survival plate measures is the rate a real system would test at, arc by arc, and it can be known in advance.

What no policy avoids is the recomputation itself. A potential that has gone negative on one arc is not repairable by fixing that arc: the potential is a set of distances from a virtual source, and one arc’s fall can lower the distance to every vertex reachable through it. An estimate is a reweighting is the reason the two are the same object seen twice — a potential that makes arcs non-negative and an estimate that guides a search are one function with two uses — and it is why a local repair is not available in either use.

A preparation is not an investment until it survives

The arithmetic of a preparation repaid over many uses is the arithmetic of amortisation, and what amortised means is the reason to be careful with it: a cost spread over a sequence of operations is a real saving only if the sequence happens. A dynamic array’s doubling is amortised over the appends that follow it and those appends are guaranteed, because nothing outside the structure can undo them.

A reweighting has no such guarantee. The sequence it is amortised over is the run of queries before the graph moves, and that run has a length the structure does not control. The churn plate is that length turned into money: at no churn the sequence is unbounded and the preparation is free; at half a per cent the sequence is one query long and the preparation is paid every time, which is the definition of not being a preparation at all.

The same shape appears wherever a structure is built in advance against a world that can change under it. Where the table starts paying priced a lookup table against recomputation and found the crossing in the number of lookups; a table over a changing domain has the crossing in how often the domain changes instead. The structure that was supposed to halve is the other failure of the same reasoning — a preparation whose stated benefit did not arrive — and this one is a preparation whose benefit arrives and then leaves.

What makes this case unusually clean is that the length of the sequence is measurable before the preparation is paid for. The per-arc break rate is a pass over the arcs; the number of arcs that move between queries is in the update log. Multiply the two and the expected run length falls out, and with the break-even at three queries the decision is a comparison of two numbers a system already has. The model a bound was quoted in is the general complaint that a bound is useless without the model it was stated under, and the model here is a static graph — stated nowhere in the description of Johnson’s method, because in the all-pairs setting there is no time for anything to change.

What the two numbers say together

A designer holding both results has a rule with no free parameters in it.

If the graph is static, store the potential. It repays itself before the third query at every density measured, and thereafter every query costs 32% less. There is no query count small enough for this to be the wrong call except one and two.

If the graph changes, measure the per-arc break rate, not the query rate. It is computable from the arcs and the potential in one pass, it was 6.6% here, and it says how many arcs may move between queries before the stored potential is a loss: about ten, on this graph, which is half a per cent of them.

And the two questions are not the same question. A system answering a million queries on a graph that changes ten arcs between each of them should not store a potential, and a system answering five queries on a graph that never changes should. The parameter the all-pairs framing puts first — how many uses the preparation is divided over — turns out not to decide anything here, and the parameter it does not mention decides everything.

What is not measured here

One graph family. Arcs cost one to nine plus the difference of a random potential on 256 vertices, which is the construction the all-pairs page used, and it is what makes the per-arc break rate 6.6%. A graph whose arc costs have a wider spread would have a looser potential and a lower rate; a graph whose shortest-path structure is nearly determined — a near-tree — would have a tighter one and a higher rate. The one part of the rate that does not depend on the family is the floor the tight arcs set, and it is the part with an argument rather than a measurement behind it.

Redraws of the same width. A redraw can move an arc’s cost by at most eight, so no single update can drive a repriced cost far below zero. An update model that halved a cost, or set it from a different distribution, would break more arcs and break them worse, and the recomputation would be no more expensive — which is the asymmetry that makes the repair proposed at the end of this page worth measuring.

Redraws from the original distribution. Every update replaces a cost with one drawn the same way, so the graph is statistically stationary and the potential’s rate does not drift. A system whose costs trend — congestion rising through a morning — faces a rate that changes while it is being measured.

No negative cycles, ever. The construction forbids them, so an update can never make the question unanswerable. A real dynamic graph can, and detecting it costs a Bellman–Ford run that the policies here would not otherwise pay for.

One recomputation policy. The potential is recomputed the moment it is invalid. A system could instead keep answering with Bellman–Ford until the next scheduled recomputation, trading a known worse per-query cost for a fixed preparation schedule; nothing here prices that.

The check itself is counted, the per-arc test is not. The scan over every arc is included in the stored method’s work above. The per-update subtraction the previous section describes is not, because no run here uses it.

Still open: a potential that is rebuilt from where it broke

Every recomputation on this page starts again from the virtual source, which throws away a potential that was correct everywhere except behind one fallen arc. That is visibly more than is needed. When an arc (u,v)(u, v) falls so that w+h(u)h(v)<0w + h(u) - h(v) < 0, the only distances that can have fallen are those of vertices reachable from vv, and the repair is the same relaxation Bellman–Ford does, started from vv with the deficit rather than from a virtual source with nothing.

The measurement that follows implements that repair, counts the arcs it has to relax against the full recomputation’s, and sweeps the churn: the prediction from this page is that at one arc an update the repaired region is a small fraction of the graph and the stored potential’s crossing moves well past half a per cent, and that as several arcs fall at once the repairs overlap until the repaired region is the whole graph and the two costs meet. Where that meeting falls, against the 6.6% per-arc rate, is the number that decides whether a routing system with negative costs can hold a potential at all.

What this makes readable

Essays that name this one as a prerequisite.

Named alongside this one

Essays reaching for the same objects. Nobody chose these; they are what the concept index makes visible.

What links here

Every essay whose body links to this one.

The objects this essay names

Each one links to every other essay that touches it.

AmortisationBreak-evenDynamic graphInvalidationNegative weightPotential functionPreprocessingRegimeReweightingShortest pathSpace time trade