Yes, and the interesting part is what it costs. On a rural corridor in Mid Wales, thirteen enrolled drivers serve 85% of thirty-two riders at 6.8 vehicle-kilometres per passenger carried. Pushing the fleet to thirty-two vehicles gains another ten points of service rate and costs 13.9 km per passenger. Pushing it to a hundred and thirty-two adds nothing and costs 58.7 km per passenger. A low-flow ridesharing service is cheap while it is short of vehicles and ruinous the moment it has enough of them.
That is the answer from 600 simulated runs across four committed experiments, every one of them reproducible offline from the repository with no API key. What follows is the argument.
North Ceredigion into Aberystwyth: five middle-layer super output areas, 44,485 residents, one town that takes the work, and seven stations across 23 km of the A487 and A44. 11,772 commutes run between the five areas; the largest single pair is 1,235 people a day, 62% of them driving alone. That is the low-flow case: thin enough that a shared ride is a real coordination problem rather than a queue.
Demand comes from the 2011 Census travel-to-work table, the most recent openly licensed area-to-area flow survey carrying a mode breakdown: it separates driving a car from riding in one, so the corridor brings with it an observed car-passenger share of 9.95% of car commutes. That is the one outside number available for asking whether a modelled occupancy is plausible at all, and not a target to tune against, which would make the whole thing circular. The stations come from OpenStreetMap, selected by rule rather than by hand. Two numbers in the corridor are invented and both are stated out loud: a scenario samples one in twenty of the observed flow and enrols one car driver in ten.
Every experiment runs the same ten seeds at every point on its axis, so two settings are never compared as two means with overlapping bands: the difference is computed seed by seed and reported as a mean, a standard deviation, and a count of how many seeds moved each way. That is not a significance test and is not offered as one.
Two conclusions in this project changed direction under it, and both had already been written down as results: a crossover between two dispatch rules that turned out to be noise, and a walking-threshold figure that was several revisions stale.
At six vehicles, two seats serve 16% of riders and five seats serve 55%. Over exactly the same 83.9 kilometres, because those drivers were making those trips anyway and the extra seats cost no distance at all. The same share of service can be reached by adding vehicles instead of seats, but the bill changes: where five seats manage it with thirteen vehicles, two seats need sixty-six, and sixty-six vehicles drive 891 km against 183. Five times the distance for the same service.
This is a statement about a corridor whose demand is thin and scattered. A vehicle passing a station is common; two riders wanting the same station at the same time is not.
The binding constraint on this service is not the dispatcher and not the fleet: it is how far somebody will walk to a station. At twenty minutes of total walking, adding vehicles stops working entirely: service goes 0.278 → 0.381 → 0.375 across a fleet that more than quintuples, so thirty-two vehicles serve no more people than thirteen and cost 37.9 km per passenger against 16.9. A rider with no line inside its own walking threshold never registers, so no amount of added supply can reach it.
The committed scenarios assume a maximum of forty minutes of walking across both ends: against the engine's thirty-minute default that is worth eleven points of service rate, on all ten seeds. The stations sit up to two kilometres from where the population actually is, because that is where they are in rural Wales.
Four constructions derive lines from the corridor's stations: free-form connects all 21 station pairs, Delaunay 14, flow-ranked 13 (the only one that reads the demand table), and the minimum spanning tree 6. The hypothesis was that structuring the network would pay. The result was unexpected.
Halving the network is free. Flow-ranked's 13 pairs against free-form's 21 differ by under 0.01 of service at every fleet size, and most seeds produce identical results. Quartering it is not. Delaunay and the tree lose 0.18 to 0.24 of service at every fleet size above six, on all ten seeds. The tree drives the fewest kilometres, but only because it serves the fewest people.
And every construction loses to six lines drawn by hand. The corridor's hand-declared network is six one-way lines, all of them into Aberystwyth. Paired seed by seed it beats free-form by 0.106 at six vehicles and 0.109 at thirteen, on all ten seeds, and only stops winning once there are so many vehicles that the ranking finds everybody anyway. Six directed lines beat forty-two directed lines.
The mechanism is direction: every construction here is symmetric, and on a radial morning commute half its lines run away from the work, where the dispatcher sometimes sends a driver. So what pays is not structure but knowing the demand's direction, which none of the four constructions reads.
The second dispatch rule drops the shared yardstick and sends each driver to the line with riders already standing on it. Paired seed by seed, it never measurably wins on service and loses on cost everywhere: its empty-distance share is worse at every fleet size, and at thirty-two vehicles it drives 234 extra kilometres, 55% more, for slightly less service. A driver that drifts towards somebody standing at a station is a driver going out of its way, and on 23 km lines that is the dominant term.
Worth being precise about a correction here, because it is the sort of thing that quietly becomes received wisdom. Looking at the means, the two rules appear to cross over: the demand-follower is ahead at small fleets and behind at large ones, and that was read as evidence of two heuristics each seeing what the other misses. But the lead at small fleets does not survive the seed-by-seed comparison: the seeds disagree about which of the two rules is ahead, so that lead is noise and only the cost difference survives. Neither rule is short of a mechanism the other has: both are short of scoring driver–rider pairs directly instead of keying a match on a line, which is the next section.
Both rules above key a match on the line both parties registered on, so a rider whose best line has no driver goes unserved even when a driver on its second choice would gladly have taken it. The third rule drops the line as the match key while keeping it as geometry: a rider still registers on its first choice and still starts walking there, but it stops being that line's property. Any driver may divert it, provided the walk it would still have to make, from wherever it has got to, is inside the threshold that rider declared. The score is a pair score: the driver's detour as a fraction of driving straight there, plus the rider's remaining walk as a fraction of its own limit. Neither party reads the other's unit, and neither threshold can be overruled by the dispatcher.
It is the first rule here to beat the ranking on service with a stable sign, and it does it only at the bottom of the fleet axis: +0.075 at six vehicles (seven seeds up of ten) and +0.053 at thirteen (eight of ten). At thirty-two the difference is exactly zero. At sixty-six and a hundred and thirty-two it goes the other way: −0.037 and −0.025, with no seed at all moving in its favour. The mechanism explains the flip: where vehicles are scarce a rider's chosen line often has nobody on it, and releasing it to whoever can reach it is a ride that would not otherwise happen; where vehicles are plentiful there is already a driver on every line, so diverting riders only moves them about.
It never wins on cost. Its empty-distance share is worse than the ranking rule's on all ten seeds at three of the five fleet sizes, and occupancy is worse on all ten seeds at four of them, and at thirteen vehicles it drives 8.6 km per passenger against 6.8. Sending a driver to collect somebody who was walking elsewhere is a real detour, and the rider's second walk is real too. Against the demand-following rule, though, it dominates: more service at thirteen and thirty-two vehicles (eight seeds up of ten, and seven), shorter waits at every fleet size, and at thirty-two it does it for 25 km less. On this corridor, though, not following demand at all remains cheaper than either rule.
Two ceilings, both deliberate. Each driver decides alone with no view of the rest of the fleet, so two of them can reach for the same rider and the first one wins; assigning across the whole fleet at once is the half that is not built. And a rider is diverted at most once, and only while it is still walking: sending somebody already standing at a station off to another one would restart the clock its patience is measured against and quietly inflate every service figure on this page.
Run the same corridor as a door-to-door robotaxi fleet and it serves 24 of 32 riders over 335 kilometres, 56% of them empty, at a mean occupancy of 0.44. The carpool service serves 27 of the same 32 over 183 km at an occupancy of 1.35, which is half the distance per passenger. The mechanism is one structural difference: a fleet vehicle has no trip of its own, so every empty kilometre is a cost the service pays, where a carpool driver's empty kilometres are somebody's commute. Adding vehicles does not correct this difference.
Two notes, and they pull in the same direction as the conclusion. These are single runs at one seed rather than a ten-seed sweep, so unlike everything above they carry no band. And every door-to-door leg is measured as a straight line while the carpool legs use real road geometry: the fleet's distance is understated and the true gap is wider.
Nothing above involved a language model, and no model figure exists yet. Every number on this page was produced by a fixed rule, offline, deterministically. What follows is an engineering claim about how you would measure one honestly, not a result about one.
The dispatcher sits behind a trait with four decisions: which line a driver takes, whether to spend a guarantee vehicle on a rider who has waited too long, which idle vehicle collects which rider, and where an idle vehicle waits. Five implementations plug into the same seam: the three fixed rules above, a model on every decision, and a model only where the first two fixed rules disagree. It is the same seam the fixed rules use, measured on the same mobility columns, with cost per decision and invalid-action rate reported beside them.
Two things make the model implementations affordable, and both are measured rather than asserted. Every decision is event-driven, so nothing costs a call per tick or per agent per tick; and every answer is memoised on the exact bytes of its context, which works only because no context carries the wall clock: a question carrying the clock is a different question every second and could never be reused. The result: 3,913 decisions in 44 calls, or 2,239 in 22 for the exceptions-only variant. Those counts were measured against a stub that answers from a rule, so they measure the machinery and say nothing about a model.
The comparison takes running a single command, at a cost of about $11 of tokens, and the bars it has to clear are written down before the run rather than after. For the line choice that is now 0.906 at thirteen vehicles, that is pair scoring and not the 0.853 of the ranking rule, because the bar moved when the third rule landed; and there is a cost baseline it must not overrun. For the network-design question it is the 0.853 of six hand-drawn one-way lines rather than the 0.750 of the best construction, because a win against the weaker opponent would not be a result. Repositioning an idle vehicle competes against doing nothing, which is a low bar. If the fixed rule wins, that is the number that gets reported.
The order of work is this: define the metric first, build the baseline, add the model, measure the delta, publish the number even when it is unflattering. An invalid action is counted and refused, never retried, because asking the same question again is the retry and a retry loop would hide exactly the number worth having. A dead model process fails the run rather than finishing under a fixed rule wearing the model's name.
No behavioural response to the incentive: a payout moves two accounting columns and nothing else, which is what keeps every other comparison valid across schemes. No fleet-wide assignment: pair scoring is greedy per driver, so two drivers can reach for the same rider, and chaining several drop-offs into one trip is the same missing computation. Two agent kinds are declared and inert, and the one scenario that contains them ends at the clock cap and is reported as cut off rather than averaged into a result. Walks to stations and every door-to-door leg take a straight-line fallback, which gets the time right and understates the distance.
Two things the write-up tries not to do. An effect that fails to separate is not an effect that has been ruled out: where ten seeds cannot tell two rules apart, that is what is reported. And a metric from a run that hit the clock cap is not a finding at all; the engine reports stranded agents separately so that a cut-off run can never be quietly averaged in.
Rust, single binary, no HTTP client and no async runtime: the one command that needs road
geometry shells out to curl and commits its output, and the model lives behind a
Python sidecar speaking line-delimited JSON over a pipe. Agents live in a flat vector and
reference each other by index; deciding is a pure function returning an influence that a later
pass resolves, which is what made the dispatcher swappable without touching a state machine. One
seeded generator owns every draw, so a run under a fixed rule is a pure function of its scenario
and its seed: the same seed writes byte-identical output, and so does a regenerated chart.
Predecessor: a Python multi-agent simulator, and a PFIA 2025 paper on network structuring for autonomous on-demand mobility. This is a rewrite that asks the cost question the earlier work could not answer.