You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MIPLearn/tests/problems/test_tsp.py

91 lines
3.2 KiB

# MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
import numpy as np
from numpy.linalg import norm
from scipy.spatial.distance import pdist, squareform
from scipy.stats import uniform, randint
from miplearn.problems.tsp import TravelingSalesmanGenerator, TravelingSalesmanInstance
from miplearn.solvers.learning import LearningSolver
def test_generator() -> None:
instances = TravelingSalesmanGenerator(
x=uniform(loc=0.0, scale=1000.0),
y=uniform(loc=0.0, scale=1000.0),
n=randint(low=100, high=101),
gamma=uniform(loc=0.95, scale=0.1),
fix_cities=True,
).generate(100)
assert len(instances) == 100
assert instances[0].n_cities == 100
assert norm(instances[0].distances - instances[0].distances.T) < 1e-6
d = [instance.distances[0, 1] for instance in instances]
assert np.std(d) > 0
def test_instance() -> None:
n_cities = 4
distances = np.array(
[
[0.0, 1.0, 2.0, 1.0],
[1.0, 0.0, 1.0, 2.0],
[2.0, 1.0, 0.0, 1.0],
[1.0, 2.0, 1.0, 0.0],
]
)
instance = TravelingSalesmanInstance(n_cities, distances)
solver = LearningSolver()
solver.solve(instance)
assert len(instance.samples) == 1
assert instance.samples[0].after_mip is not None
features = instance.samples[0].after_mip
assert features is not None
assert features.variables is not None
assert features.variables["x[(0, 1)]"].value == 1.0
assert features.variables["x[(0, 2)]"].value == 0.0
assert features.variables["x[(0, 3)]"].value == 1.0
assert features.variables["x[(1, 2)]"].value == 1.0
assert features.variables["x[(1, 3)]"].value == 0.0
assert features.variables["x[(2, 3)]"].value == 1.0
assert features.mip_solve is not None
assert features.mip_solve.mip_lower_bound == 4.0
assert features.mip_solve.mip_upper_bound == 4.0
def test_subtour() -> None:
n_cities = 6
cities = np.array(
[
[0.0, 0.0],
[1.0, 0.0],
[2.0, 0.0],
[3.0, 0.0],
[0.0, 1.0],
[3.0, 1.0],
]
)
distances = squareform(pdist(cities))
instance = TravelingSalesmanInstance(n_cities, distances)
solver = LearningSolver()
solver.solve(instance)
assert len(instance.samples) == 1
assert instance.samples[0].after_mip is not None
features = instance.samples[0].after_mip
assert features.extra is not None
assert "lazy_enforced" in features.extra
lazy_enforced = features.extra["lazy_enforced"]
assert lazy_enforced is not None
assert len(lazy_enforced) > 0
assert features.variables is not None
assert features.variables["x[(0, 1)]"].value == 1.0
assert features.variables["x[(0, 4)]"].value == 1.0
assert features.variables["x[(1, 2)]"].value == 1.0
assert features.variables["x[(2, 3)]"].value == 1.0
assert features.variables["x[(3, 5)]"].value == 1.0
assert features.variables["x[(4, 5)]"].value == 1.0
solver.fit([instance])
solver.solve(instance)