Skip to content

Commit

Permalink
Minor things for 5.1.0 release (#151)
Browse files Browse the repository at this point in the history
* Minor quality of life updates

Including dependency version bumps

* Update CVRP notebook to use vrplib

And stop using the old cvprlib package

* Bump ALNS version to 5.1.0
  • Loading branch information
N-Wouda committed May 7, 2023
1 parent 9a03619 commit c04f2e4
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 36 deletions.
13 changes: 4 additions & 9 deletions alns/show_versions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import sys

# TODO switch over to importlib.metadata once we drop support for Python 3.7
import pkg_resources # type: ignore
from importlib.metadata import version


def show_versions():
Expand All @@ -23,14 +21,11 @@ def show_versions():
matplotlib: 3.5.1
Python: 3.9.9
"""
alns = pkg_resources.get_distribution("alns")
numpy = pkg_resources.get_distribution("numpy")
matplotlib = pkg_resources.get_distribution("matplotlib")
python_version = ".".join(map(str, sys.version_info[:3]))

print("INSTALLED VERSIONS")
print("------------------")
print(f" alns: {alns.version}")
print(f" numpy: {numpy.version}")
print(f"matplotlib: {matplotlib.version}")
print(f" alns: {version('alns')}")
print(f" numpy: {version('numpy')}")
print(f"matplotlib: {version('matplotlib')}")
print(f" Python: {python_version}")
47 changes: 24 additions & 23 deletions examples/capacitated_vehicle_routing_problem.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
"outputs": [],
"source": [
"import copy\n",
"from types import SimpleNamespace\n",
"\n",
"import cvrplib\n",
"import vrplib\n",
"import matplotlib\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
Expand Down Expand Up @@ -70,7 +71,7 @@
},
"source": [
"## Data\n",
"[CVRPLIB](http://vrp.atd-lab.inf.puc-rio.br/index.php/en/) contains a large collection of CVRP benchmark instances. The library is actively maintained and new best known solutions are updated regularly. We use the `cvrplib` package to read the `ORTEC-n242-k12` instance, which consists of 241 customers (+ 1 depot) and 12 vehicles, but we assume that an unlimited number of vehicles is available."
"[CVRPLIB](http://vrp.atd-lab.inf.puc-rio.br/index.php/en/) contains a large collection of CVRP benchmark instances. The library is actively maintained and new best known solutions are updated regularly. We use the `vrplib` package to read the `ORTEC-n242-k12` instance, which consists of 241 customers (+ 1 depot) and 12 vehicles, but we assume that an unlimited number of vehicles is available."
]
},
{
Expand All @@ -82,7 +83,8 @@
},
"outputs": [],
"source": [
"data, bks = cvrplib.read('data/ORTEC-n242-k12.vrp', 'data/ORTEC-n242-k12.sol')"
"data = vrplib.read_instance('data/ORTEC-n242-k12.vrp')\n",
"bks = SimpleNamespace(**vrplib.read_solution('data/ORTEC-n242-k12.sol'))"
]
},
{
Expand Down Expand Up @@ -113,15 +115,15 @@
"\n",
" for idx, route in enumerate(solution.routes):\n",
" ax.plot(\n",
" [data.coordinates[loc][0] for loc in [0] + route + [0]],\n",
" [data.coordinates[loc][1] for loc in [0] + route + [0]],\n",
" [data[\"node_coord\"][loc][0] for loc in [0] + route + [0]],\n",
" [data[\"node_coord\"][loc][1] for loc in [0] + route + [0]],\n",
" color=cmap[idx],\n",
" marker='.'\n",
" )\n",
" \n",
" # Plot the depot\n",
" kwargs = dict(label=\"Depot\", zorder=3, marker=\"*\", s=750)\n",
" ax.scatter(*data.coordinates[0], c=\"tab:red\", **kwargs) \n",
" ax.scatter(*data[\"node_coord\"][0], c=\"tab:red\", **kwargs) \n",
"\n",
" ax.set_title(f\"{name}\\n Total distance: {solution.cost}\")\n",
" ax.set_xlabel(\"X-coordinate\")\n",
Expand Down Expand Up @@ -216,8 +218,11 @@
" raise ValueError(f\"Solution does not contain customer {customer}.\")\n",
" \n",
"def route_cost(route):\n",
" distances = data[\"edge_weight\"]\n",
" tour = [0] + route + [0]\n",
" return sum(data.distances[tour[idx]][tour[idx+1]] for idx in range(len(tour) - 1))"
"\n",
" return sum(distances[tour[idx]][tour[idx + 1]]\n",
" for idx in range(len(tour) - 1))"
]
},
{
Expand Down Expand Up @@ -250,7 +255,7 @@
"outputs": [],
"source": [
"degree_of_destruction = 0.05\n",
"customers_to_remove = int((data.dimension - 1) * degree_of_destruction)"
"customers_to_remove = int((data[\"dimension\"] - 1) * degree_of_destruction)"
]
},
{
Expand All @@ -269,7 +274,7 @@
" destroyed = state.copy()\n",
"\n",
" for customer in rnd_state.choice(\n",
" range(1, data.dimension), customers_to_remove, replace=False\n",
" range(1, data[\"dimension\"]), customers_to_remove, replace=False\n",
" ):\n",
" destroyed.unassigned.append(customer)\n",
" route = destroyed.find_route(customer)\n",
Expand Down Expand Up @@ -348,24 +353,20 @@
" \"\"\"\n",
" Checks if inserting customer does not exceed vehicle capacity.\n",
" \"\"\"\n",
" total = sum(data.demands[cust] for cust in route) + data.demands[customer]\n",
" return total <= data.capacity\n",
" total = data[\"demand\"][route].sum() + data[\"demand\"][customer]\n",
" return total <= data[\"capacity\"]\n",
"\n",
"\n",
"def insert_cost(customer, route, idx):\n",
" \"\"\"\n",
" Computes the insertion cost for inserting customer in route at idx.\n",
" \"\"\"\n",
" dist = data[\"edge_weight\"]\n",
" pred = 0 if idx == 0 else route[idx - 1]\n",
" succ = 0 if idx == len(route) else route[idx]\n",
"\n",
" # Increase in cost by adding the customer\n",
" cost = data.distances[pred][customer] + data.distances[customer][succ]\n",
"\n",
" # Decrease in cost by removing old edge (pred, succ)\n",
" cost -= data.distances[pred][succ]\n",
"\n",
" return cost"
" # Increase in cost of adding customer, minus cost of removing old edge\n",
" return dist[pred][customer] + dist[customer][succ] - dist[pred][succ]"
]
},
{
Expand All @@ -392,7 +393,7 @@
" \"\"\"\n",
" Return the nearest neighbors of the customer, excluding the depot.\n",
" \"\"\"\n",
" locations = np.argsort(data.distances[customer])\n",
" locations = np.argsort(data[\"edge_weight\"][customer])\n",
" return locations[locations != 0]\n",
"\n",
"\n",
Expand All @@ -402,7 +403,7 @@
" customer is added until the route has met the vehicle capacity limit.\n",
" \"\"\"\n",
" routes = []\n",
" unvisited = list(range(1, data.dimension))\n",
" unvisited = set(range(1, data[\"dimension\"]))\n",
"\n",
" while unvisited:\n",
" route = [0] # Start at the depot\n",
Expand All @@ -413,12 +414,12 @@
" current = route[-1]\n",
" nearest = [nb for nb in neighbors(current) if nb in unvisited][0]\n",
"\n",
" if route_demands + data.demands[nearest] > data.capacity:\n",
" if route_demands + data[\"demand\"][nearest] > data[\"capacity\"]:\n",
" break\n",
"\n",
" route.append(nearest)\n",
" unvisited.remove(nearest)\n",
" route_demands += data.demands[nearest]\n",
" route_demands += data[\"demand\"][nearest]\n",
"\n",
" customers = route[1:] # Remove the depot\n",
" routes.append(customers)\n",
Expand Down Expand Up @@ -617,7 +618,7 @@
" max_string_removals = min(len(state.routes), MAX_STRING_REMOVALS)\n",
"\n",
" destroyed_routes = []\n",
" center = rnd_state.randint(1, data.dimension)\n",
" center = rnd_state.randint(1, data[\"dimension\"])\n",
"\n",
" for customer in neighbors(center):\n",
" if len(destroyed_routes) >= max_string_removals:\n",
Expand Down
10 changes: 6 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "alns"
version = "5.0.4"
version = "5.1.0"
description = "A flexible implementation of the adaptive large neighbourhood search (ALNS) algorithm."
authors = ["Niels Wouda <nielswouda@gmail.com>"]
license = "MIT"
Expand All @@ -15,10 +15,10 @@ packages = [
classifiers = [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"Development Status :: 5 - Production/Stable",
Expand All @@ -32,9 +32,11 @@ classifiers = [
[tool.poetry.dependencies]
python = "^3.8, <4.0"
numpy = ">=1.18.0"
matplotlib = ">=2.2.0"
matplotlib = ">=3.5.0"

[tool.poetry.dev-dependencies]
# This group is needed to develop the package itself.
[tool.poetry.group.dev.dependencies]
vrplib = "^1.0.1"
pre-commit = "^2.20.0"
pytest = ">=6.0.0"
pytest-cov = ">=2.6.1"
Expand Down

0 comments on commit c04f2e4

Please sign in to comment.