Skip to content
GIS for History

A least-cost path is the route between two points that costs the least total effort to travel, measured over a "cost surface" that says how hard each patch of land is to cross — not simply the shortest straight line. In historical GIS it is a way to generate a defensible hypothesis about where a road, droveway or pilgrimage route might have run, given the terrain. This guide explains the idea in plain language and walks through a small example.

What is a least-cost path?

Imagine the landscape as a grid of cells. Crossing a flat meadow is cheap; climbing a steep hill or fording a marsh is expensive. A cost surface assigns each cell a number for that difficulty. The algorithm then finds the route from A to B whose cells add up to the smallest total — the path of least resistance.

The key shift for a beginner: "distance" stops meaning kilometres and starts meaning effort. A longer route around a hill can be cheaper than a short route over it.

How do you build a cost surface?

Start from a digital elevation model (DEM) and turn terrain into friction:

  1. Compute slope from the DEM.
  2. Convert slope to a movement cost with a cost function (see below).
  3. Optionally add barriers — set rivers, cliffs or marsh to very high cost.
bash
# GRASS GIS: slope from a DEM, then a simple cost surface
r.slope.aspect elevation=dem slope=slope_deg
# higher slope = higher cost (toy linear example)
r.mapcalc "cost = 1.0 + (slope_deg / 10.0)"

Real studies use a published cost function rather than a linear guess.

How does slope become a cost?

The standard choice is Tobler's hiking function, which estimates walking speed from slope. Travel time per cell becomes your cost, and because steep climbs and steep descents are slow, cost rises on both sides of flat:

text
speed (km/h) ≈ 6 * exp(-3.5 * |slope + 0.05|)
cost per cell ≈ cell_length / speed   # time to cross

Using time-based cost makes the result interpretable: the path that takes the least time, not the least map distance.

A small worked example

With a cost surface ready, two GRASS steps produce the route:

bash
# accumulate cost outward from the start point
r.cost input=cost output=cost_accum start_coordinates=412000,328000
# trace the cheapest path back from the destination
r.drain input=cost_accum output=route \
        start_coordinates=455000,351000 -d

r.cost floods the landscape with accumulated cost from the origin; r.drain then walks downhill through that accumulated surface to the destination, tracing the least-cost path.

Does the path prove a route existed?

No — and this is the crux. A least-cost path is a hypothesis: "if travellers minimised effort and my cost assumptions are right, this is where they would go." It is most valuable when compared against independent evidence:

OutputWhat it isWhat it is not
Least-cost pathAn effort-optimal hypothesisA documented road
Cost surfaceYour terrain assumptionsObjective truth
Corridor (top X%)A plausibility bandA precise line

Where the modelled path coincides with known milestones or earthworks, the model gains credibility. Where it diverges, that divergence is itself an interesting finding.

What mistakes should beginners avoid?

The single biggest error is trusting one run. Cost weights are guesses, so test their influence. Re-run with steeper and gentler slope penalties, with and without river barriers, and see whether the route holds. A path that survives several reasonable assumptions is a robust hypothesis; one that jumps around is an artefact. Reporting a corridor (the cheapest few percent of cells) is often more honest than a single hairline.

Key Takeaways

  • A least-cost path minimises accumulated effort over a cost surface, not straight-line distance.
  • Build the cost surface from a DEM: slope to friction, plus barriers for rivers and marsh.
  • Tobler's hiking function turns slope into travel time, the most interpretable cost.
  • r.cost accumulates cost; r.drain traces the cheapest path back.
  • The result is a hypothesis to test against archaeology and texts, never proof.
  • Always run a sensitivity test on the cost weights.
  • Reporting a corridor is often more honest than one precise line.

Frequently Asked Questions

What is a least-cost path in historical GIS?

It is the route between two places that minimises total accumulated 'cost' — usually travel effort rather than straight-line distance — across a cost surface that encodes how hard each cell of the landscape is to cross.

What is a cost surface?

A raster grid where each cell holds a number for how costly it is to move through that location. It is built from inputs like slope, rivers, marsh or vegetation, often combined into a single friction value.

Does a least-cost path prove where a real Roman road ran?

No. It produces a hypothesis: the most efficient route given your cost assumptions. It is evidence to compare against archaeology and texts, not proof on its own.

How does slope become a movement cost?

Through a cost function such as Tobler's hiking function, which converts the slope between cells into walking speed or time. Steeper uphill and steep downhill both slow travel, so cost rises with gradient.

Which tools compute least-cost paths?

QGIS (the GRASS r.cost and r.drain tools), GRASS GIS directly, ArcGIS Cost Distance / Cost Path, and Python via scikit-image's MCP or the open-source 'leastcostpath' R package.

What is the biggest beginner mistake?

Treating the output as fact and not testing how sensitive it is to the cost assumptions. Always re-run with different friction weights to see whether the route is robust or an artefact of one guess.