|
import argparse |
|
import os |
|
import numpy as np |
|
from utils.data_utils import check_extension, save_dataset |
|
|
|
|
|
def generate_tsp_data(dataset_size, tsp_size): |
|
return np.random.uniform(size=(dataset_size, tsp_size, 2)).tolist() |
|
|
|
|
|
def generate_vrp_data(dataset_size, vrp_size): |
|
CAPACITIES = { |
|
10: 20., |
|
20: 30., |
|
50: 40., |
|
75: 45., |
|
100: 50. |
|
} |
|
theta = 2*np.pi * np.random.uniform(size = (dataset_size, vrp_size)) |
|
data_point = 0.5*np.ones((dataset_size, vrp_size, 2)) + np.stack([ 0.5* np.cos(theta), 0.5* np.sin(theta)], axis = 2) |
|
demand_point = CAPACITIES[vrp_size]/vrp_size* np.ones((dataset_size, vrp_size)) |
|
|
|
return list(zip( |
|
(0.5*np.ones((dataset_size, 2))).tolist(), |
|
data_point.tolist(), |
|
demand_point.tolist(), |
|
np.full(dataset_size, CAPACITIES[vrp_size]).tolist() |
|
)) |
|
|
|
|
|
def generate_op_data(dataset_size, op_size, prize_type='const'): |
|
depot = np.random.uniform(size=(dataset_size, 2)) |
|
loc = np.random.uniform(size=(dataset_size, op_size, 2)) |
|
|
|
|
|
if prize_type == 'const': |
|
prize = np.ones((dataset_size, op_size)) |
|
elif prize_type == 'unif': |
|
prize = (1 + np.random.randint(0, 100, size=(dataset_size, op_size))) / 100. |
|
else: |
|
assert prize_type == 'dist' |
|
prize_ = np.linalg.norm(depot[:, None, :] - loc, axis=-1) |
|
prize = (1 + (prize_ / prize_.max(axis=-1, keepdims=True) * 99).astype(int)) / 100. |
|
|
|
|
|
|
|
MAX_LENGTHS = { |
|
20: 2., |
|
50: 3., |
|
100: 4. |
|
} |
|
|
|
return list(zip( |
|
depot.tolist(), |
|
loc.tolist(), |
|
prize.tolist(), |
|
np.full(dataset_size, MAX_LENGTHS[op_size]).tolist() |
|
)) |
|
|
|
|
|
def generate_pctsp_data(dataset_size, pctsp_size, penalty_factor=3): |
|
depot = np.random.uniform(size=(dataset_size, 2)) |
|
loc = np.random.uniform(size=(dataset_size, pctsp_size, 2)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MAX_LENGTHS = { |
|
20: 2., |
|
50: 3., |
|
100: 4. |
|
} |
|
penalty_max = MAX_LENGTHS[pctsp_size] * (penalty_factor) / float(pctsp_size) |
|
penalty = np.random.uniform(size=(dataset_size, pctsp_size)) * penalty_max |
|
|
|
|
|
|
|
|
|
|
|
deterministic_prize = np.random.uniform(size=(dataset_size, pctsp_size)) * 4 / float(pctsp_size) |
|
|
|
|
|
|
|
|
|
|
|
stochastic_prize = np.random.uniform(size=(dataset_size, pctsp_size)) * deterministic_prize * 2 |
|
|
|
return list(zip( |
|
depot.tolist(), |
|
loc.tolist(), |
|
penalty.tolist(), |
|
deterministic_prize.tolist(), |
|
stochastic_prize.tolist() |
|
)) |
|
|
|
|
|
if __name__ == "__main__": |
|
parser = argparse.ArgumentParser() |
|
parser.add_argument("--filename", help="Filename of the dataset to create (ignores datadir)") |
|
parser.add_argument("--data_dir", default='data', help="Create datasets in data_dir/problem (default 'data')") |
|
parser.add_argument("--name", type=str, required=True, help="Name to identify dataset") |
|
parser.add_argument("--problem", type=str, default='all', |
|
help="Problem, 'tsp', 'vrp', 'pctsp' or 'op_const', 'op_unif' or 'op_dist'" |
|
" or 'all' to generate all") |
|
parser.add_argument('--data_distribution', type=str, default='all', |
|
help="Distributions to generate for problem, default 'all'.") |
|
|
|
parser.add_argument("--dataset_size", type=int, default=10000, help="Size of the dataset") |
|
parser.add_argument('--graph_sizes', type=int, nargs='+', default=[10, 20, 50,75, 100], |
|
help="Sizes of problem instances (default 20, 50, 100)") |
|
parser.add_argument("-f", action='store_true', help="Set true to overwrite") |
|
parser.add_argument('--seed', type=int, default=1234, help="Random seed") |
|
|
|
opts = parser.parse_args() |
|
|
|
assert opts.filename is None or (len(opts.problems) == 1 and len(opts.graph_sizes) == 1), \ |
|
"Can only specify filename when generating a single dataset" |
|
|
|
distributions_per_problem = { |
|
'tsp': [None], |
|
'vrp': [None], |
|
'pctsp': [None], |
|
'op': ['const', 'unif', 'dist'] |
|
} |
|
if opts.problem == 'all': |
|
problems = distributions_per_problem |
|
else: |
|
problems = { |
|
opts.problem: |
|
distributions_per_problem[opts.problem] |
|
if opts.data_distribution == 'all' |
|
else [opts.data_distribution] |
|
} |
|
|
|
for problem, distributions in problems.items(): |
|
for distribution in distributions or [None]: |
|
for graph_size in opts.graph_sizes: |
|
|
|
datadir = os.path.join(opts.data_dir, problem) |
|
os.makedirs(datadir, exist_ok=True) |
|
|
|
if opts.filename is None: |
|
filename = os.path.join(datadir, "{}{}{}_{}_seed{}.pkl".format( |
|
problem, |
|
"_{}".format(distribution) if distribution is not None else "", |
|
graph_size, opts.name, opts.seed)) |
|
else: |
|
filename = check_extension(opts.filename) |
|
|
|
assert opts.f or not os.path.isfile(check_extension(filename)), \ |
|
"File already exists! Try running with -f option to overwrite." |
|
|
|
np.random.seed(opts.seed) |
|
if problem == 'tsp': |
|
dataset = generate_tsp_data(opts.dataset_size, graph_size) |
|
elif problem == 'vrp': |
|
dataset = generate_vrp_data( |
|
opts.dataset_size, graph_size) |
|
elif problem == 'pctsp': |
|
dataset = generate_pctsp_data(opts.dataset_size, graph_size) |
|
elif problem == "op": |
|
dataset = generate_op_data(opts.dataset_size, graph_size, prize_type=distribution) |
|
else: |
|
assert False, "Unknown problem: {}".format(problem) |
|
|
|
print(dataset[0]) |
|
|
|
save_dataset(dataset, filename) |
|
|