Skip to content

Commit

Permalink
✨ Parsing tspwp problems
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrickOHara committed Nov 27, 2020
1 parent 61dac04 commit 4b20412
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 20 deletions.
6 changes: 4 additions & 2 deletions tests/test_complete.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""Test that all existing instances are complete graphs"""

import networkx as nx
from tspwplib.dataset import load_tsplib_dataset
import tsplib95
from tspwplib.utils import build_path_to_tsplib_instance


def test_tsplib_is_complete(tsplib_root, instance_name):
"""Test each instance of TSPLIB95 is a complete graph"""
problem = load_tsplib_dataset(tsplib_root, instance_name)
filepath = build_path_to_tsplib_instance(tsplib_root, instance_name)
problem = tsplib95.load(filepath)
graph = problem.get_graph()
assert nx.complete_graph(graph)
34 changes: 34 additions & 0 deletions tests/test_profits_problem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Test the TSP with Profits Problem class"""

import math
import networkx as nx
from tspwplib.problem import ProfitsProblem
from tspwplib.types import OptimalSolutionTSP
from tspwplib.utils import build_path_to_oplib_instance


def test_parse_profits_problem(oplib_root, generation, instance_name, alpha):
"""Test an OP instance can be parsed"""
filepath = build_path_to_oplib_instance(
oplib_root, generation, instance_name, alpha=alpha
)
assert "COST_LIMIT" in ProfitsProblem.fields_by_keyword

problem = ProfitsProblem.load(filepath)
assert problem.is_complete()
graph = problem.get_graph()
assert nx.complete_graph(graph)


def test_get_cost_limit(oplib_root, generation, instance_name, alpha):
"""Test we can get the cost limit"""
filepath = build_path_to_oplib_instance(
oplib_root, generation, instance_name, alpha=alpha
)
problem = ProfitsProblem.load(filepath)
# total_cost = sum([problem.get_weight(source, target) for source, target in problem.get_edges()])

expected_cost_limit = math.ceil(
OptimalSolutionTSP[instance_name] * (alpha.value / 100.0)
)
assert problem.get_cost_limit() == expected_cost_limit
17 changes: 0 additions & 17 deletions tspwplib/dataset.py

This file was deleted.

40 changes: 40 additions & 0 deletions tspwplib/problem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Functions and classes for datasets"""

from typing import Dict
import tsplib95


class ProfitsProblem(tsplib95.models.StandardProblem):
"""TSP with Profits Problem"""

# Maximum distance of the total route in a OP.
cost_limit = tsplib95.fields.IntegerField("COST_LIMIT")
# The scores of the nodes of a OP are given in the form (per line)
node_score = tsplib95.fields.DemandsField("NODE_SCORE_SECTION")
# The optimal solution to the TSP
tspsol = tsplib95.fields.IntegerField("TSPSOL")
# TODO add profit limit for PcTSP

def get_cost_limit(self) -> int:
"""Get the cost limit for a TSP with Profits problem
Returns:
Cost limit
"""
return self.cost_limit

def get_node_score(self) -> Dict[int, int]:
"""Get the node scores (profits)
Returns:
Mapping from node to node score (profit)
"""
# TODO

def get_tsp_optimal_value(self) -> int:
"""Get the value of the optimal solution to TSP
Returns:
TSP optimal value
"""
return self.tspsol
119 changes: 118 additions & 1 deletion tspwplib/types.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Type hinting and names"""

from enum import Enum
from enum import Enum, IntEnum


class InstanceName(str, Enum):
Expand All @@ -25,3 +25,120 @@ class Alpha(Enum):
"""Ratio between profit/cost limit and profit/cost of TSP solution"""

fifty = 50


class OptimalSolutionTSP(IntEnum):
"""Value of optimal solutions to TSP instances"""

a280 = 2579
ali535 = 202339
att48 = 10628
att532 = 27686
bayg29 = 1610
bays29 = 2020
berlin52 = 7542
bier127 = 118282
brazil58 = 25395
brd14051 = 469385
brg180 = 1950
burma14 = 3323
ch130 = 6110
ch150 = 6528
d198 = 15780
d493 = 35002
d657 = 48912
d1291 = 50801
d1655 = 62128
d2103 = 80450
d15112 = 1573084
d18512 = 645238
dantzig42 = 699
dsj1000 = 18659688 # (EUC_2D)
# dsj1000 = 18660188 # (CEIL_2D) # NOTE breaks keys
eil51 = 426
eil76 = 538
eil101 = 629
fl417 = 11861
fl1400 = 20127
fl1577 = 22249
fl3795 = 28772
fnl4461 = 182566
fri26 = 937
gil262 = 2378
gr17 = 2085
gr21 = 2707
gr24 = 1272
gr48 = 5046
gr96 = 55209
gr120 = 6942
gr137 = 69853
gr202 = 40160
gr229 = 134602
gr431 = 171414
gr666 = 294358
hk48 = 11461
kroA100 = 21282
kroB100 = 22141
kroC100 = 20749
kroD100 = 21294
kroE100 = 22068
kroA150 = 26524
kroB150 = 26130
kroA200 = 29368
kroB200 = 29437
lin105 = 14379
lin318 = 42029
linhp318 = 41345
nrw1379 = 56638
p654 = 34643
pa561 = 2763
pcb442 = 50778
pcb1173 = 56892
pcb3038 = 137694
pla7397 = 23260728
pla33810 = 66048945
pla85900 = 142382641
pr76 = 108159
pr107 = 44303
pr124 = 59030
pr136 = 96772
pr144 = 58537
pr152 = 73682
pr226 = 80369
pr264 = 49135
pr299 = 48191
pr439 = 107217
pr1002 = 259045
pr2392 = 378032
rat99 = 1211
rat195 = 2323
rat575 = 6773
rat783 = 8806
rd100 = 7910
rd400 = 15281
rl1304 = 252948
rl1323 = 270199
rl1889 = 316536
rl5915 = 565530
rl5934 = 556045
rl11849 = 923288
si175 = 21407
si535 = 48450
si1032 = 92650
st70 = 675
swiss42 = 1273
ts225 = 126643
tsp225 = 3916
u159 = 42080
u574 = 36905
u724 = 41910
u1060 = 224094
u1432 = 152970
u1817 = 57201
u2152 = 64253
u2319 = 234256
ulysses16 = 6859
ulysses22 = 7013
usa13509 = 19982859
vm1084 = 239297
vm1748 = 336556

0 comments on commit 4b20412

Please sign in to comment.