Esempio n. 1
0
    def test_k4(self):
        # good routes are 0,1,2,3 or 3,2,1,0 (and their rotations)
        G = nx.Graph()
        G.add_weighted_edges_from([(0, 1, 1), (1, 2, 1), (2, 3, 1), (3, 0, 1),
                                   (0, 2, 2), (1, 3, 2)])

        Q = tsp.traveling_salesperson_qubo(G, lagrange=10)
        bqm = dimod.BinaryQuadraticModel.from_qubo(Q)

        # good routes won't have 0<->2 or 1<->3
        min_routes = [(0, 1, 2, 3), (1, 2, 3, 0), (2, 3, 0, 1), (1, 2, 3, 0),
                      (3, 2, 1, 0), (2, 1, 0, 3), (1, 0, 3, 2), (0, 3, 2, 1)]

        # get the min energy of the qubo
        sampleset = dimod.ExactSolver().sample(bqm)
        ground_energy = sampleset.first.energy

        # all possible routes are equally good
        for route in min_routes:
            sample = {v: 0 for v in bqm}
            for idx, city in enumerate(route):
                sample[(city, idx)] = 1
            self.assertAlmostEqual(bqm.energy(sample), ground_energy)

        # all min-energy solutions are valid routes
        ground_count = 0
        for sample, energy in sampleset.data(['sample', 'energy']):
            if abs(energy - ground_energy) > .001:
                break
            ground_count += 1

        self.assertEqual(ground_count, len(min_routes))
Esempio n. 2
0
    def test_k4_equal_weights(self):
        # k5 with all equal weights so all paths are equally good
        G = nx.Graph()
        G.add_weighted_edges_from(
            (u, v, .5) for u, v in itertools.combinations(range(4), 2))

        Q = tsp.traveling_salesperson_qubo(G, lagrange=10)
        bqm = dimod.BinaryQuadraticModel.from_qubo(Q)

        # all routes are min weight
        min_routes = list(itertools.permutations(G.nodes))

        # get the min energy of the qubo
        sampleset = dimod.ExactSolver().sample(bqm)
        ground_energy = sampleset.first.energy

        # all possible routes are equally good
        for route in min_routes:
            sample = {v: 0 for v in bqm}
            for idx, city in enumerate(route):
                sample[(city, idx)] = 1
            self.assertAlmostEqual(bqm.energy(sample), ground_energy)

        # all min-energy solutions are valid routes
        ground_count = 0
        for sample, energy in sampleset.data(['sample', 'energy']):
            if abs(energy - ground_energy) > .001:
                break
            ground_count += 1

        self.assertEqual(ground_count, len(min_routes))
Esempio n. 3
0
    def test_docstring_size(self):
        # in the docstring we state the size of the resulting BQM, this checks
        # that
        for n in range(3, 20):
            G = nx.Graph()
            G.add_weighted_edges_from(
                (u, v, .5) for u, v in itertools.combinations(range(n), 2))
            Q = tsp.traveling_salesperson_qubo(G)
            bqm = dimod.BinaryQuadraticModel.from_qubo(Q)

            self.assertEqual(len(bqm), n**2)
            self.assertEqual(len(bqm.quadratic), 2 * n * n * (n - 1))
Esempio n. 4
0
    def test_weighted_complete_graph(self):
        G = nx.Graph()
        G.add_weighted_edges_from({(0, 1, 1), (0, 2, 100), (0, 3, 1),
                                   (1, 2, 1), (1, 3, 100), (2, 3, 1)})

        lagrange = 5.0

        Q = tsp.traveling_salesperson_qubo(G, lagrange, 'weight')

        N = G.number_of_nodes()
        correct_sum = G.size(
            'weight') * 2 * N - 2 * N * N * lagrange + 2 * N * N * (
                N - 1) * lagrange

        actual_sum = sum(Q.values())

        self.assertEqual(correct_sum, actual_sum)
Esempio n. 5
0
 def test_exceptions(self):
     G = nx.Graph([(0, 1)])
     with self.assertRaises(ValueError):
         tsp.traveling_salesperson_qubo(G)
Esempio n. 6
0
 def test_empty(self):
     Q = tsp.traveling_salesperson_qubo(nx.Graph())
     self.assertEqual(Q, {})
Esempio n. 7
0
def TSP_solver(G, token=None):
    """
    The TSP_solver function actually uses Ocean SDK and a call to dwave's
    computer to solve the Traveling Salesperson Problem.

    :param G: This is the networkx graph to be solved.
        Usually the output of make_graph is directly plugged into this.

    :return: It returns the route as a List, a directed networkx graph,
        and the cost of the route.
    """
    endpoint = 'https://cloud.dwavesys.com/sapi/'
    client = 'qpu'
    #solver = 'DW_2000Q_5' # Use this to specify a solver, but leave commented out to let D-Wave's system autochoose a solver
    try:
        qpu_sampler = DWaveSampler(client=client,
                                   endpoint=endpoint,
                                   token=token)
        #solver=solver)
    except Exception as e:
        print(e)
        return {'error': 'Token not accepted'}

    # Lagrange multiplier, to weigh the constraints versus the mileage
    lagrange = 8000

    n = len(G)

    # Use dwave_networkx method to get the QUBO
    Q = traveling_salesperson_qubo(G, lagrange=lagrange)

    # Include the energy offset so that the energy comes out in miles
    offset = 2 * n * lagrange

    # Choose a sampler
    # sampler = TabuSampler()
    sampler = KerberosSampler()

    # Get a BQM and run the problem
    bqm = dimod.BinaryQuadraticModel.from_qubo(Q, offset=offset)
    # response = sampler.sample(bqm)
    response = sampler.sample(bqm,
                              max_iter=1,
                              convergence=1,
                              qpu_sampler=qpu_sampler)

    # Turn the bitstring result into a trip/loop
    start = None
    sample = response.first.sample
    cost = response.first.energy
    route = [None] * n

    for (city, time), val in sample.items():
        if val:
            route[time] = city

    if start is not None and route[0] != start:
        # rotate to put the start in front
        idx = route.index(start)
        route = route[-idx:] + route[:-idx]

    # If there is a valid solution, print it
    if None not in route:
        ans = nx.Graph()

        tmp_edges = []

        for i in range(0, len(route) - 1):
            tmp_edges.append((route[i], route[i + 1],
                              G.get_edge_data(route[i], route[i + 1])))

        ans.add_weighted_edges_from(tmp_edges)

        print(route)
        print(cost)
        print(ans)
    else:
        print("No valid solution")
        route = None
        cost = None
        ans = None

    return route, cost, ans