Skip to content

Commit cd93eb1

Browse files
committed
Initial commit
1 parent d044b55 commit cd93eb1

24 files changed

+2463
-1
lines changed

.gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

.gitignore

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Custom
2+
main.py
3+
data/
4+
logs/
5+
relics/
6+
.idea/
7+
8+
# Byte-compiled / optimized / DLL files
9+
__pycache__/
10+
*.py[cod]
11+
*$py.class
12+
13+
# C extensions
14+
*.so
15+
16+
# Distribution / packaging
17+
.Python
18+
build/
19+
develop-eggs/
20+
dist/
21+
downloads/
22+
eggs/
23+
.eggs/
24+
lib/
25+
lib64/
26+
parts/
27+
sdist/
28+
var/
29+
wheels/
30+
*.egg-info/
31+
.installed.cfg
32+
*.egg
33+
MANIFEST
34+
35+
# PyInstaller
36+
# Usually these files are written by a python script from a template
37+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
38+
*.manifest
39+
*.spec
40+
41+
# Installer logs
42+
pip-log.txt
43+
pip-delete-this-directory.txt
44+
45+
# Unit test / coverage reports
46+
htmlcov/
47+
.tox/
48+
.coverage
49+
.coverage.*
50+
.cache
51+
nosetests.xml
52+
coverage.xml
53+
*.cover
54+
.hypothesis/
55+
.pytest_cache/
56+
57+
# Translations
58+
*.mo
59+
*.pot
60+
61+
# Django stuff:
62+
*.log
63+
local_settings.py
64+
db.sqlite3
65+
66+
# Flask stuff:
67+
instance/
68+
.webassets-cache
69+
70+
# Scrapy stuff:
71+
.scrapy
72+
73+
# Sphinx documentation
74+
docs/_build/
75+
76+
# PyBuilder
77+
target/
78+
79+
# Jupyter Notebook
80+
.ipynb_checkpoints
81+
82+
# pyenv
83+
.python-version
84+
85+
# celery beat schedule file
86+
celerybeat-schedule
87+
88+
# SageMath parsed files
89+
*.sage.py
90+
91+
# Environments
92+
.env
93+
.venv
94+
env/
95+
venv/
96+
ENV/
97+
env.bak/
98+
venv.bak/
99+
100+
# Spyder project settings
101+
.spyderproject
102+
.spyproject
103+
104+
# Rope project settings
105+
.ropeproject
106+
107+
# mkdocs documentation
108+
/site
109+
110+
# mypy
111+
.mypy_cache/

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2019 Chaitanya Joshi
3+
Copyright (c) 2019 Chaitanya Joshi, Thomas Laurent, Xavier Bresson
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# An Efficient Graph Convolutional Network for the Travelling Salesman Problem
2+
3+
This repository contains code for the paper
4+
"An Efficient Graph Convolutional Network for the Travelling Salesman Problem"
5+
by Chaitanya K. Joshi, Thomas Laurent and Xavier Bresson.
6+
7+
We introduce a new learning-based approach for approximately solving the
8+
Travelling Salesman Problem on 2D Euclidean graphs.
9+
We use deep Graph Convolutional Networks to build efficient TSP graph representations
10+
and output tours in a non-autoregressive manner via highly parallelized beam search.
11+
Our approach outperforms all recently proposed autoregressive deep learning
12+
techniques in terms of solution quality, inference speed and sample efficiency
13+
for problem instances of fixed graph sizes.
14+
15+
![model-blocks](/res/model-blocks.png)
16+
17+
# Overview
18+
19+
The notebook `main.ipynb` contains top-level methods to reproduce our experiments or train models for TSP from scratch.
20+
Several modes are provided:
21+
- **Notebook Mode**: For debugging as a Jupyter Notebook
22+
- **Visualization Mode**: For visualization and evaluation of saved model checkpoints (in a Jupyter Notebook)
23+
- **Script Mode**: For running full experiments as a python script
24+
25+
Configuration parameters for notebooks and scripts are passed as `.json` files and are documented in `config.py`.
26+
27+
# Pre-requisite Downloads
28+
29+
1. Download TSP datasets from [this link](https://drive.google.com/open?id=1-5W-S5e7CKsJ9uY9uVXIyxgbcZZNYBrp), extract the `.tar.gz` file, and place each `.txt` file in the `/data` directory. (We provide TSP10, TSP20, TSP30, TSP50 and TSP100.)
30+
2. Download pre-trained model checkpoints from [this link](https://drive.google.com/open?id=1qmk1_5a8XT_hrOV_i3uHM9tMVnZBFEAF), extract the `.tar.gz` file, and place each directory in the `/logs` directory. (We provide TSP20, TSP50 and TSP100 models.) .
31+
32+
# Usage
33+
34+
## Installation
35+
Step-by-step guide for local installation using a Terminal (Mac/Linux) or Git Bash (Windows):
36+
1. Install [Anaconda 3](https://www.anaconda.com/) for managing Python packages and environments.
37+
```sh
38+
curl -o ~/miniconda.sh -O https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
39+
chmod +x ~/miniconda.sh
40+
./miniconda.sh
41+
source ~/.bashrc
42+
```
43+
2. Clone the repository.
44+
```sh
45+
git clone https://github.com/chaitjo/graph-convnet-tsp.git
46+
cd graph-convnet-tsp
47+
```
48+
3. Set up a new conda environment and activate it.
49+
```sh
50+
conda create -n gcn-tsp-env python=3.6.7
51+
source activate gcn-tsp-env
52+
```
53+
4. Install all dependencies and Jupyter Lab (for using notebooks).
54+
```sh
55+
conda install pytorch=0.4.1 cuda90 -c pytorch
56+
conda install numpy==1.15.4 scipy==1.1.0 matplotlib==3.0.2 seaborn==0.9.0 pandas==0.24.2 networkx==2.2 scikit-learn==0.20.2 tensorflow-gpu==1.12.0 tensorboard==1.12.0
57+
pip3 install tensorboardx==1.5 fastprogress==0.1.18
58+
conda install -c conda-forge jupyterlab
59+
```
60+
61+
## Running in Notebook/Visualization Mode
62+
Launch Jupyter Lab and execute/modify `main.ipynb` cell-by-cell in Notebook Mode.
63+
```sh
64+
jupyter lab
65+
```
66+
67+
Set `viz_mode = True` in the first cell of `main.ipynb` to toggle Visualization Mode.
68+
69+
## Running in Script Mode
70+
0. Set `notebook_mode = False` and `viz_mode = False` in the first cell of `main.ipynb`.
71+
1. Convert from .ipynb to .py: `jupyter nbconvert --to python main.ipynb`
72+
2. Run the script (pass path of configuration file as arguement): `python main.py --config <path-to-config.json>`
73+
74+
## Splitting datasets into Training and Validation sets
75+
For TSP10, TSP20 and TSP30 datasets, everything is good to go.
76+
For TSP50 and TSP100, the 1M training set needs to be split into 10K validation samples and 999K training samples.
77+
Use the `split_train_val.ipynb` notebook to do this through Jupyter Lab.

config.py

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import json
2+
3+
4+
class Settings(dict):
5+
"""Experiment configuration options.
6+
7+
Wrapper around in-built dict class to access members through the dot operation.
8+
9+
Experiment parameters:
10+
"expt_name": Name/description of experiment, used for logging.
11+
"gpu_id": Available GPU ID(s)
12+
13+
"train_filepath": Training set path
14+
"val_filepath": Validation set path
15+
"test_filepath": Test set path
16+
17+
"num_nodes": Number of nodes in TSP tours
18+
"num_neighbors": Number of neighbors in k-nearest neighbor input graph (-1 for fully connected)
19+
20+
"node_dim": Number of dimensions for each node
21+
"voc_nodes_in": Input node signal vocabulary size
22+
"voc_nodes_out": Output node prediction vocabulary size
23+
"voc_edges_in": Input edge signal vocabulary size
24+
"voc_edges_out": Output edge prediction vocabulary size
25+
26+
"beam_size": Beam size for beamsearch procedure (-1 for disabling beamsearch)
27+
28+
"hidden_dim": Dimension of model's hidden state
29+
"num_layers": Number of GCN layers
30+
"mlp_layers": Number of MLP layers
31+
"aggregation": Node aggregation scheme in GCN (`mean` or `sum`)
32+
33+
"max_epochs": Maximum training epochs
34+
"val_every": Interval (in epochs) at which validation is performed
35+
"test_every": Interval (in epochs) at which testing is performed
36+
37+
"batch_size": Batch size
38+
"batches_per_epoch": Batches per epoch (-1 for using full training set)
39+
"accumulation_steps": Number of steps for gradient accumulation (DO NOT USE: BUGGY)
40+
41+
"learning_rate": Initial learning rate
42+
"decay_rate": Learning rate decay parameter
43+
"""
44+
45+
def __init__(self, config_dict):
46+
super().__init__()
47+
for key in config_dict:
48+
self[key] = config_dict[key]
49+
50+
def __getattr__(self, attr):
51+
return self[attr]
52+
53+
def __setitem__(self, key, value):
54+
return super().__setitem__(key, value)
55+
56+
def __setattr__(self, key, value):
57+
return self.__setitem__(key, value)
58+
59+
__delattr__ = dict.__delitem__
60+
61+
62+
def get_default_config():
63+
"""Returns default settings object.
64+
"""
65+
return Settings(json.load(open("./configs/default.json")))
66+
67+
68+
def get_config(filepath):
69+
"""Returns settings from json file.
70+
"""
71+
config = get_default_config()
72+
config.update(Settings(json.load(open(filepath))))
73+
return config

configs/default.json

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"expt_name": "deafult",
3+
"gpu_id": "0",
4+
5+
"train_filepath": "./data/tsp10_train_concorde.txt",
6+
"val_filepath": "./data/tsp10_val_concorde.txt",
7+
"test_filepath": "./data/tsp10_test_concorde.txt",
8+
9+
"num_nodes": 10,
10+
"num_neighbors": 5,
11+
12+
"node_dim": 2,
13+
"voc_nodes_in": 2,
14+
"voc_nodes_out": 2,
15+
"voc_edges_in": 3,
16+
"voc_edges_out": 2,
17+
18+
"beam_size": 10,
19+
20+
"hidden_dim": 50,
21+
"num_layers": 3,
22+
"mlp_layers": 2,
23+
"aggregation": "mean",
24+
25+
"max_epochs": 10,
26+
"val_every": 5,
27+
"test_every": 10,
28+
29+
"batch_size": 20,
30+
"batches_per_epoch": 500,
31+
"accumulation_steps": 1,
32+
33+
"learning_rate": 0.001,
34+
"decay_rate": 1.01
35+
}

configs/tsp10.json

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"expt_name": "tsp10",
3+
"gpu_id": "0",
4+
5+
"train_filepath": "./data/tsp10_train_concorde.txt",
6+
"val_filepath": "./data/tsp10_val_concorde.txt",
7+
"test_filepath": "./data/tsp10_test_concorde.txt",
8+
9+
"num_nodes": 10,
10+
"num_neighbors": -1,
11+
12+
"node_dim": 2,
13+
"voc_nodes_in": 2,
14+
"voc_nodes_out": 2,
15+
"voc_edges_in": 3,
16+
"voc_edges_out": 2,
17+
18+
"beam_size": 1280,
19+
20+
"hidden_dim": 300,
21+
"num_layers": 30,
22+
"mlp_layers": 3,
23+
"aggregation": "mean",
24+
25+
"max_epochs": 1500,
26+
"val_every": 5,
27+
"test_every": 100,
28+
29+
"batch_size": 20,
30+
"batches_per_epoch": 500,
31+
"accumulation_steps": 1,
32+
33+
"learning_rate": 0.001,
34+
"decay_rate": 1.01
35+
}

configs/tsp100.json

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"expt_name": "tsp100",
3+
"gpu_id": "0,1,2,3",
4+
5+
"train_filepath": "./data/tsp100_train_concorde.txt",
6+
"val_filepath": "./data/tsp100_val_concorde.txt",
7+
"test_filepath": "./data/tsp100_test_concorde.txt",
8+
9+
"num_nodes": 100,
10+
"num_neighbors": 20,
11+
12+
"node_dim": 2,
13+
"voc_nodes_in": 2,
14+
"voc_nodes_out": 2,
15+
"voc_edges_in": 3,
16+
"voc_edges_out": 2,
17+
18+
"beam_size": 1280,
19+
20+
"hidden_dim": 300,
21+
"num_layers": 30,
22+
"mlp_layers": 3,
23+
"aggregation": "mean",
24+
25+
"max_epochs": 1500,
26+
"val_every": 5,
27+
"test_every": 100,
28+
29+
"batch_size": 20,
30+
"batches_per_epoch": 500,
31+
"accumulation_steps": 1,
32+
33+
"learning_rate": 0.001,
34+
"decay_rate": 1.01
35+
}

0 commit comments

Comments
 (0)