Datasets¶
skroute.datasets bundles two families of routing instances and a reader for the
TSPLIB 95 file format. Nothing is downloaded: every file ships inside the wheel.
- 27 Waterloo national TSP instances — the populated places of a country as
planar coordinates with the tour length published by the University of
Waterloo under the TSPLIB
EUC_2Dmetric (a proven optimum for 25 of them). Load one withload_tsp("wi29")or its country wrapperload_sahara(). - Five road-cost tables — small multi-trip instances (Alicante–Murcia, Barcelona, Madrid, Valencia and Qatar) with cost, time and distance matrices retrieved from the Google Distance Matrix API.
Loaders return a Bunch: a dict whose keys are also
attributes. The matrices carry no labels — they are plain float64 arrays —
so pass labels=b.labels (and depot=b.depot) to fit or to
RoutingProblem, or ask for as_frame=True and get labelled DataFrames.
>>> from skroute.datasets import load_tsp, load_barcelona
>>> wi = load_tsp("wi29")
>>> wi.coords.shape, wi.depot, wi.optimal_tour_length
((29, 2), 1, 27603)
>>> C = wi.distance_matrix() # built once, cached; never built by the loader
>>> C.shape
(29, 29)
>>> bcn = load_barcelona()
>>> bcn.cost.shape, bcn.depot, bcn.units
((19, 19), 10000007, {'cost': 'EUR', 'time': 'h', 'distance': 'm'})
The 27 Waterloo instances¶
All 27 use EDGE_WEIGHT_TYPE: EUC_2D, so the distance between two cities is
nint(sqrt(dx² + dy²)) with nint(x) = floor(x + 0.5) — what
TSPBunch.distance_matrix() computes. Tour lengths are those published by the
University of Waterloo (status of 2022-07-31): proven optima for 25 instances,
while bm33708 and ch71009 are still open, so their optimal_tour_length is
the best-known tour — within 0.031 % and 0.024 % of the lower bound — and not a
proven optimum. The four instances above 20 000 nodes cannot be solved whole in
scikit-route 2.0 (every solver works on a dense matrix; the one of ch71009
would take 40 GB): distance_matrix() refuses them unless force=True, and
load_tsp(name, n_nodes=5000) gives a subsample whose optimum is unknown.
| Name | Country | Wrapper | Cities | Tour length |
|---|---|---|---|---|
wi29 |
Western Sahara | load_sahara |
29 | 27 603 |
dj38 |
Djibouti | load_djibouti |
38 | 6 656 |
qa194 |
Qatar | load_qatar |
194 | 9 352 |
uy734 |
Uruguay | load_uruguay |
734 | 79 114 |
zi929 |
Zimbabwe | load_zimbabwe |
929 | 95 345 |
lu980 |
Luxembourg | load_luxembourg |
980 | 11 340 |
rw1621 |
Rwanda | load_rwanda |
1 621 | 26 051 |
mu1979 |
Oman | load_oman |
1 979 | 86 891 |
nu3496 |
Nicaragua | load_nicaragua |
3 496 | 96 132 |
ca4663 |
Canada | load_canada |
4 663 | 1 290 319 |
tz6117 |
Tanzania | load_tanzania |
6 117 | 394 718 |
eg7146 |
Egypt | load_egypt |
7 146 | 172 386 |
ym7663 |
Yemen | load_yemen |
7 663 | 238 314 |
pm8079 |
Panama | load_panama |
8 079 | 114 855 |
ei8246 |
Ireland | load_ireland |
8 246 | 206 171 |
ar9152 |
Argentina | load_argentina |
9 152 | 837 479 |
ja9847 |
Japan | load_japan |
9 847 | 491 924 |
gr9882 |
Greece | load_greece |
9 882 | 300 899 |
kz9976 |
Kazakhstan | load_kazakhstan |
9 976 | 1 061 881 |
fi10639 |
Finland | load_finland |
10 639 | 520 527 |
mo14185 |
Morocco | load_morocco |
14 185 | 427 377 |
ho14473 |
Honduras | load_honduras |
14 473 | 177 092 |
it16862 |
Italy | load_italy |
16 862 | 557 315 |
vm22775 |
Vietnam | load_vietnam |
22 775 | 569 288 |
sw24978 |
Sweden | load_sweden |
24 978 | 855 597 |
bm33708 |
Burma | load_burma |
33 708 | 959 289 † |
ch71009 |
China | load_china |
71 009 | 4 566 506 † |
† Best-known tour, not proven optimal (Waterloo's lower bounds are 959 011 and 4 565 452).
Source: W. Cook et al., National Traveling Salesman Problems, University of Waterloo, https://www.math.uwaterloo.ca/tsp/world/countries.html; status table at https://www.math.uwaterloo.ca/tsp/world/summary.html.
load_tsp ¶
load_tsp(name: str, *, n_nodes: int | None = None, random_state: int | None = 2019, mode: str | None = None) -> TSPBunch
Load one of the 27 Waterloo national TSP instances bundled with scikit-route.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Instance name, e.g. |
required |
n_nodes
|
int
|
Keep only |
None
|
random_state
|
int or None
|
Seed of the subsampling (only used with |
2019
|
mode
|
('small', 'medium', 'big')
|
Deprecated 1.0 spelling of |
"small"
|
Returns:
| Type | Description |
|---|---|
TSPBunch
|
With |
Notes
The four instances above 20 000 nodes (vm22775, sw24978, bm33708,
ch71009) cannot be solved whole in 2.0 (dense matrices only); their
DESCR says so and shows load_tsp(name, n_nodes=5000). bm33708 and
ch71009 are still open problems: their optimal_tour_length is the
best-known tour, within 0.031 % and 0.024 % of Waterloo's lower bound, and the
DESCR says so too.
References
W. Cook et al., National Traveling Salesman Problems, University of Waterloo, https://www.math.uwaterloo.ca/tsp/world/countries.html; status table at https://www.math.uwaterloo.ca/tsp/world/summary.html
Examples:
>>> from skroute.datasets import load_tsp
>>> wi = load_tsp("wi29")
>>> wi.coords.shape, wi.labels[:3].tolist(), wi.depot, wi.optimal_tour_length
((29, 2), [1, 2, 3], 1, 27603)
>>> small = load_tsp("qa194", n_nodes=20, random_state=0)
>>> small.coords.shape, int(small.labels[0]), small.optimal_tour_length
((20, 2), 1, None)
list_tsp ¶
TSPBunch ¶
Bases: Bunch
A Bunch of a coordinate instance with a cached distance_matrix().
Behaves like a dict with attribute access (b.coords or b["coords"]);
keys() lists only the data fields. The distance matrix is a method, so it
is never built by the loader and is cached under the private attribute
_distance_matrix (not a key).
Examples:
>>> from skroute.datasets import load_tsp
>>> b = load_tsp("wi29")
>>> sorted(b)
['DESCR', 'coords', 'depot', 'edge_weight_type', 'labels', 'name', 'optimal_tour_length']
>>> C = b.distance_matrix()
>>> C.shape, C is b.distance_matrix() # (n, n) and cached
((29, 29), True)
distance_matrix ¶
The dense (n, n) matrix under the instance's TSPLIB metric, computed once and cached.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
force
|
bool
|
Build the matrix even above 20 000 nodes (a |
False
|
Returns:
| Type | Description |
|---|---|
ndarray of shape (n, n), dtype float64
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
Above 20 000 nodes without |
Country wrappers¶
Each one is load_tsp("<name>", ...) under its 1.0 name and accepts the same
n_nodes=, random_state= and (deprecated) mode= keywords. As in 1.0, mode
may also be the first positional argument (load_qatar("small")); it emits the
same DeprecationWarning.
load_sahara ¶
load_sahara(mode: str | None = None, **kwargs: Any) -> TSPBunch
Western Sahara, wi29 (29 cities, optimum 27603); load_tsp("wi29", **kwargs).
load_djibouti ¶
load_djibouti(mode: str | None = None, **kwargs: Any) -> TSPBunch
Djibouti, dj38 (38 cities, optimum 6656); load_tsp("dj38", **kwargs).
load_qatar ¶
load_qatar(mode: str | None = None, **kwargs: Any) -> TSPBunch
Qatar, qa194 (194 cities, optimum 9352); load_tsp("qa194", **kwargs).
load_uruguay ¶
load_uruguay(mode: str | None = None, **kwargs: Any) -> TSPBunch
Uruguay, uy734 (734 cities, optimum 79114); load_tsp("uy734", **kwargs).
load_zimbabwe ¶
load_zimbabwe(mode: str | None = None, **kwargs: Any) -> TSPBunch
Zimbabwe, zi929 (929 cities, optimum 95345); load_tsp("zi929", **kwargs).
load_luxembourg ¶
load_luxembourg(mode: str | None = None, **kwargs: Any) -> TSPBunch
Luxembourg, lu980 (980 cities, optimum 11340); load_tsp("lu980", **kwargs).
load_rwanda ¶
load_rwanda(mode: str | None = None, **kwargs: Any) -> TSPBunch
Rwanda, rw1621 (1621 cities, optimum 26051); load_tsp("rw1621", **kwargs).
load_oman ¶
load_oman(mode: str | None = None, **kwargs: Any) -> TSPBunch
Oman, mu1979 (1979 cities, optimum 86891); load_tsp("mu1979", **kwargs).
load_nicaragua ¶
load_nicaragua(mode: str | None = None, **kwargs: Any) -> TSPBunch
Nicaragua, nu3496 (3496 cities, optimum 96132); load_tsp("nu3496", **kwargs).
load_canada ¶
load_canada(mode: str | None = None, **kwargs: Any) -> TSPBunch
Canada, ca4663 (4663 cities, optimum 1290319); load_tsp("ca4663", **kwargs).
load_tanzania ¶
load_tanzania(mode: str | None = None, **kwargs: Any) -> TSPBunch
Tanzania, tz6117 (6117 cities, optimum 394718); load_tsp("tz6117", **kwargs).
load_egypt ¶
load_egypt(mode: str | None = None, **kwargs: Any) -> TSPBunch
Egypt, eg7146 (7146 cities, optimum 172386); load_tsp("eg7146", **kwargs).
load_yemen ¶
load_yemen(mode: str | None = None, **kwargs: Any) -> TSPBunch
Yemen, ym7663 (7663 cities, optimum 238314); load_tsp("ym7663", **kwargs).
load_panama ¶
load_panama(mode: str | None = None, **kwargs: Any) -> TSPBunch
Panama, pm8079 (8079 cities, optimum 114855); load_tsp("pm8079", **kwargs).
load_ireland ¶
load_ireland(mode: str | None = None, **kwargs: Any) -> TSPBunch
Ireland, ei8246 (8246 cities, optimum 206171); load_tsp("ei8246", **kwargs).
load_argentina ¶
load_argentina(mode: str | None = None, **kwargs: Any) -> TSPBunch
Argentina, ar9152 (9152 cities, optimum 837479); load_tsp("ar9152", **kwargs).
load_japan ¶
load_japan(mode: str | None = None, **kwargs: Any) -> TSPBunch
Japan, ja9847 (9847 cities, optimum 491924); load_tsp("ja9847", **kwargs).
load_greece ¶
load_greece(mode: str | None = None, **kwargs: Any) -> TSPBunch
Greece, gr9882 (9882 cities, optimum 300899); load_tsp("gr9882", **kwargs).
load_kazakhstan ¶
load_kazakhstan(mode: str | None = None, **kwargs: Any) -> TSPBunch
Kazakhstan, kz9976 (9976 cities, optimum 1061881); load_tsp("kz9976", **kwargs).
load_finland ¶
load_finland(mode: str | None = None, **kwargs: Any) -> TSPBunch
Finland, fi10639 (10639 cities, optimum 520527); load_tsp("fi10639", **kwargs).
load_morocco ¶
load_morocco(mode: str | None = None, **kwargs: Any) -> TSPBunch
Morocco, mo14185 (14185 cities, optimum 427377); load_tsp("mo14185", **kwargs).
load_honduras ¶
load_honduras(mode: str | None = None, **kwargs: Any) -> TSPBunch
Honduras, ho14473 (14473 cities, optimum 177092); load_tsp("ho14473", **kwargs).
load_italy ¶
load_italy(mode: str | None = None, **kwargs: Any) -> TSPBunch
Italy, it16862 (16862 cities, optimum 557315); load_tsp("it16862", **kwargs).
load_vietnam ¶
load_vietnam(mode: str | None = None, **kwargs: Any) -> TSPBunch
Vietnam, vm22775 (22775 cities, optimum 569288); load_tsp("vm22775", **kwargs).
Above the 20 000-node dense-matrix ceiling of 2.0: subsample with n_nodes=.
load_sweden ¶
load_sweden(mode: str | None = None, **kwargs: Any) -> TSPBunch
Sweden, sw24978 (24978 cities, optimum 855597); load_tsp("sw24978", **kwargs).
Above the 20 000-node dense-matrix ceiling of 2.0: subsample with n_nodes=.
load_burma ¶
load_burma(mode: str | None = None, **kwargs: Any) -> TSPBunch
Burma, bm33708 (33708 cities, best-known tour 959289); load_tsp("bm33708", **kwargs).
Above the 20 000-node dense-matrix ceiling of 2.0: subsample with n_nodes=. Still an
open problem: optimal_tour_length is the best-known tour (within 0.031 % of the lower
bound), not a proven optimum.
load_china ¶
load_china(mode: str | None = None, **kwargs: Any) -> TSPBunch
China, ch71009 (71009 cities, best-known tour 4566506); load_tsp("ch71009", **kwargs).
Above the 20 000-node dense-matrix ceiling of 2.0: subsample with n_nodes=. Still an
open problem: optimal_tour_length is the best-known tour (within 0.024 % of the lower
bound), not a proven optimum.
Road-cost tables¶
Five long tables of (origin, destination, cost, time, distance) rows pivoted
into symmetric matrices with
pairs_to_matrix. cost is in EUR
(the Spanish files) or kilometres (Qatar, which has no money column), time in
hours, distance in metres; coords are (latitude, longitude) in decimal
degrees and depot is the first id of each file. The Spanish time matrices
come from the hours column of the tables, which adds a fixed 7-minute stop to
every leg (hours = (secs + 420) / 3600). The Qatar table records the pair
(104, 111) as 0 m / 0 s although the two places are about 4 km apart; the
matrices reproduce that zero (see the DESCR).
| Loader | Places | Depot | cost unit |
Rows in the table |
|---|---|---|---|---|
load_alicante_murcia |
8 | 10000002 |
EUR | 36 |
load_barcelona |
19 | 10000007 |
EUR | 190 |
load_madrid |
18 | 10000016 |
EUR | 171 |
load_valencia |
14 | 10000022 |
EUR | 105 |
load_qatar_costs |
192 | 1 |
km | 18 336 |
load_alicante_murcia ¶
load_alicante_murcia(*, as_frame: bool = False) -> Bunch
Road costs between 8 places of Alicante and Murcia (Spain); depot 10000002.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
as_frame
|
bool
|
Return |
False
|
Returns:
| Type | Description |
|---|---|
Bunch
|
|
Notes
The matrices carry no labels: pass labels=b.labels, depot=b.depot to fit.
Parsed with the stdlib csv module (the addresses contain commas).
Examples:
load_barcelona ¶
load_barcelona(*, as_frame: bool = False) -> Bunch
Road costs between 19 places of Barcelona (Spain); depot 10000007.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
as_frame
|
bool
|
Return |
False
|
Returns:
| Type | Description |
|---|---|
Bunch
|
|
Examples:
load_madrid ¶
load_madrid(*, as_frame: bool = False) -> Bunch
Road costs between 18 places of Madrid (Spain); depot 10000016.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
as_frame
|
bool
|
Return labelled |
False
|
Returns:
| Type | Description |
|---|---|
Bunch
|
|
Examples:
load_valencia ¶
load_valencia(*, as_frame: bool = False) -> Bunch
Road costs between 14 places of Valencia (Spain); depot 10000022.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
as_frame
|
bool
|
Return labelled |
False
|
Returns:
| Type | Description |
|---|---|
Bunch
|
|
Examples:
load_qatar_costs ¶
load_qatar_costs(*, as_frame: bool = False) -> Bunch
Road distances and driving times between 192 places of Qatar; depot 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
as_frame
|
bool
|
Return labelled |
False
|
Returns:
| Type | Description |
|---|---|
Bunch
|
|
Notes
In 1.0 load_costs_qatar() returned the Valencia table; that name survives as a
deprecated alias of this function.
The source table records the pair (104, 111) as 0 m / 0 s although the two
places are about 4 km apart, so cost, time and distance each hold one
zero off the diagonal (the Spanish tables have none). It is kept as in the source;
fill it (e.g. with the haversine distance) if your use needs positive legs.
Examples:
TSPLIB reader¶
Pure-Python readers for the TSPLIB 95 formats. read_tsplib handles the
coordinate types EUC_2D, CEIL_2D, MAN_2D, ATT and GEO (coordinates are
returned raw; convert them with
distance_matrix and the matching
tsplib_* metric) and EXPLICIT matrices in the formats FULL_MATRIX,
UPPER_ROW, LOWER_ROW, UPPER_DIAG_ROW and LOWER_DIAG_ROW; other
edge-weight types raise ValueError("... is not supported in this version").
Both readers tolerate KEY : value and KEY: value, CRLF line endings, a UTF-8
BOM, UTF-8 or latin-1 text, data written on the section keyword's own line and a
missing EOF.
read_tsplib ¶
read_tsplib(path_or_file: str | PathLike[str] | IO[str] | IO[bytes]) -> Bunch
Read a TSPLIB 95 .tsp file (coordinates or an explicit matrix).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path_or_file
|
path-like or file object
|
Path of the file, or an open text/binary file object. |
required |
Returns:
| Type | Description |
|---|---|
Bunch
|
With the fields
|
Raises:
| Type | Description |
|---|---|
ValueError
|
For an unsupported |
Notes
Tolerant of KEY : value and KEY: value (dj38.tsp mixes both), CRLF
line endings, indented data lines, data tokens on the section keyword's own line,
a UTF-8 BOM, UTF-8 or latin-1 text, and a missing EOF. Sections this reader
does not use (DEMAND_SECTION, FIXED_EDGES_SECTION, ...) are skipped;
check type when reading anything other than a plain TSP. Pure Python: no
pandas, no regular expressions.
References
G. Reinelt, TSPLIB 95, Universitaet Heidelberg, 1995.
Examples:
>>> import io
>>> from skroute.datasets import read_tsplib
>>> text = "NAME: tiny\nTYPE: TSP\nDIMENSION: 3\nEDGE_WEIGHT_TYPE: EUC_2D\n" \
... "NODE_COORD_SECTION\n1 0 0\n2 3 4\n3 6 8\nEOF\n"
>>> b = read_tsplib(io.StringIO(text))
>>> b.name, b.dimension, b.edge_weight_type, b.coords.shape, b.labels.tolist()
('tiny', 3, 'EUC_2D', (3, 2), [1, 2, 3])
>>> text = "NAME: m3\nTYPE: TSP\nDIMENSION: 3\nEDGE_WEIGHT_TYPE: EXPLICIT\n" \
... "EDGE_WEIGHT_FORMAT: UPPER_ROW\nEDGE_WEIGHT_SECTION\n5 9\n4\nEOF\n"
>>> read_tsplib(io.StringIO(text)).cost.tolist()
[[0.0, 5.0, 9.0], [5.0, 0.0, 4.0], [9.0, 4.0, 0.0]]
read_tsplib_tour ¶
Read a TSPLIB 95 .tour file and return the node ids of its first tour.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path_or_file
|
path-like or file object
|
Path of the file, or an open text/binary file object. |
required |
Returns:
| Type | Description |
|---|---|
ndarray of int64, shape (n,)
|
The ids of the |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the file has no |
Examples: