Aegean Placement

Twenty real Aegean ports, and the question of where to put a handful of supply depots among them. Asked two ways — and the difference between the two ways is the point.

Nothing here is computed on our side. The page loads a WebAssembly module, Go's runtime bridge and a packed coastline — three static files — and solves everything locally. There is no endpoint behind this page. Nothing on this page touches a chain.

One algorithm has a proof. The other does not.

Max-coverage — guaranteed

Serve as much population as possible within a radius of some depot. Coverage is monotone and submodular, so plain greedy is proven to return at least 63.2% of the true optimum — that is 1 − 1/e, and it is a worst case, known before the solver runs.

p-median — no guarantee

Minimize total weighted travel to the nearest depot. There is no approximation bound for the interchange heuristic that solves it. It is very good in practice and it is guaranteed nothing, and this page never calls its answer optimal.

Up to 4 depots the page also runs an exhaustive search and shows the true optimum beside the heuristic's answer, so you watch the bound hold rather than take our word for it. Past 4 the exhaustive search stops being cheap, and the page says the optimum was not computed rather than going quiet about it.

The map

Problem

Loading the solver…

The answer

The ports

Every port below is a real place, and its weight is its population. Total demand across the 20 ports is 7980753.

The demand points, largest first. Rendered from the dataset on the server, so this table is here whether or not WebAssembly is.
PortCountryPopulationLatLon
AthensGreece 3242000 37.985 23.731
İzmirTurkey 2587000 38.438 27.150
ThessalonikiGreece 828000 40.698 22.883
PiraeusGreece 466065 37.950 23.700
IraklioGreece 137154 35.325 25.130
VolosGreece 110632 39.370 22.950
ÇanakkaleTurkey 87791 40.146 26.406
HaniaGreece 78728 35.512 24.016
ChalkidaGreece 71842 38.464 23.612
KavalaGreece 59240 40.941 24.402
RodosGreece 56969 36.441 28.223
KateriniGreece 53293 40.272 22.502
AlexandroupoliGreece 52979 40.849 25.874
LamiaGreece 47246 38.899 22.434
MitiliniGreece 29328 39.110 26.555
HiosGreece 26891 38.368 26.136
KosGreece 19244 36.894 27.289
ErmoupoliGreece 12260 37.450 24.933
SitiaGreece 8833 35.200 26.099
PolygyrosGreece 5258 40.381 23.453

Where the data comes from

Coastline and ports are Natural Earth 1:10m, public domain. The map is decimated with Ramer-Douglas-Peucker at 0.002°, and that figure is read from the artifact's own header rather than typed here. Ports are the populated places inside the crop that sit within 12 km of a coastline vertex — a computed filter, not a hand-picked list. Population is Natural Earth's POP_MAX, used as the demand weight and nothing else: it is not a claim about a port's throughput or a current census.

The crop stops at the Dardanelles. A box reaching far enough north for Kavala and Alexandroupoli also reaches over the strait and picks up Istanbul, which is not an Aegean port and has more people than the rest of the table combined — every depot would go there and the map would be one dot.

The solver is a separate public module: github.com/pigfox/aegean-solver. p-median interchange, lazy-greedy max-coverage and the distance model, with their own tests and 100% statement coverage. The bound is checked there against exhaustive search over 480 instances rather than cited.