Exemple #1
0
    def test_digraph_missing_edges(self):
        G1 = nx.DiGraph()
        G1.add_weighted_edges_from([
            ('a', 'b', 0.5),
            ('b', 'a', 0.8),
            ('b', 'c', 1.0),
            ('c', 'b', 0.7),
            ('a', 'c', 2.0),
            ('c', 'a', 2.0),
        ])
        Q1 = dnx.traveling_salesperson_qubo(G1, lagrange=10)

        G2 = nx.DiGraph()
        G2.add_weighted_edges_from([
            ('a', 'b', 0.5),
            ('b', 'a', 0.8),
            ('c', 'b', 0.7),
            ('a', 'c', 2.0),
            ('c', 'a', 2.0),
        ])

        # make sure that missing_edge_weight gets applied correctly
        Q2 = dnx.traveling_salesperson_qubo(G2,
                                            lagrange=10,
                                            missing_edge_weight=1.0)

        self.assertDictEqual(Q1, Q2)
Exemple #2
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 = dnx.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.variables}
            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))
Exemple #3
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 = dnx.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.variables}
            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))
Exemple #4
0
    def test_k3_bidirectional(self):
        G = nx.DiGraph()
        G.add_weighted_edges_from([('a', 'b', 0.5), ('b', 'a', 0.5),
                                   ('b', 'c', 1.0), ('c', 'b', 1.0),
                                   ('a', 'c', 2.0), ('c', 'a', 2.0)])

        Q = dnx.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.variables}
            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))
Exemple #5
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 = dnx.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))
Exemple #6
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 = dnx.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)
Exemple #7
0
def traveling_salesperson(G,
                          sampler=None,
                          lagrange=None,
                          weight='weight',
                          start=None,
                          **sampler_args):
    # get lists with all cities
    list_cities = list(G.nodes())

    # Get a QUBO representation of the problem
    Q = dnx.traveling_salesperson_qubo(G, lagrange, weight)

    # use the sampler to find low energy states
    response = sampler.sample_qubo(Q, **sampler_args)
    sample = response.first.sample

    # fill route with None values
    route = [None] * len(G)
    # get cities from sample
    # NOTE: Prevent duplicate city entries by enforcing only one occurrence per city along route
    for (city, time), val in sample.items():
        if val and (city not in route):
            route[time] = city

    # run heuristic replacing None values
    if None in route:
        # get not assigned cities
        cities_unassigned = [city for city in list_cities if city not in route]
        cities_unassigned = list(np.random.permutation(cities_unassigned))
        for idx, city in enumerate(route):
            if city == None:
                route[idx] = cities_unassigned[0]
                cities_unassigned.remove(route[idx])

    # cycle solution to start at provided start location
    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]

    return route
Exemple #8
0
 def test_exceptions(self):
     G = nx.Graph([(0, 1)])
     with self.assertRaises(ValueError):
         dnx.traveling_salesperson_qubo(G)
Exemple #9
0
 def test_empty(self):
     Q = dnx.traveling_salesperson_qubo(nx.Graph())
     self.assertEqual(Q, {})
def traveling_salesperson(G,
                          sampler=None,
                          lagrange=None,
                          weight='weight',
                          start=None,
                          **sampler_args):
    """Returns an approximate minimum traveling salesperson route.

    Defines a QUBO with ground states corresponding to the
    minimum routes and uses the sampler to sample
    from it.

    A route is a cycle in the graph that reaches each node exactly once.
    A minimum route is a route with the smallest total edge weight.

    Parameters
    ----------
    G : NetworkX graph
        The graph on which to find a minimum traveling salesperson route.
        This should be a complete graph with non-zero weights on every edge.

    sampler :
        A binary quadratic model sampler. A sampler is a process that
        samples from low energy states in models defined by an Ising
        equation or a Quadratic Unconstrained Binary Optimization
        Problem (QUBO). A sampler is expected to have a 'sample_qubo'
        and 'sample_ising' method. A sampler is expected to return an
        iterable of samples, in order of increasing energy. If no
        sampler is provided, one must be provided using the
        `set_default_sampler` function.

    lagrange : number, optional (default None)
        Lagrange parameter to weight constraints (visit every city once)
        versus objective (shortest distance route).

    weight : optional (default 'weight')
        The name of the edge attribute containing the weight.

    start : node, optional
        If provided, the route will begin at `start`.

    sampler_args :
        Additional keyword parameters are passed to the sampler.

    Returns
    -------
    route : list
       List of nodes in order to be visited on a route

    Examples
    --------

    >>> import dimod
    ...
    >>> G = nx.Graph()
    >>> G.add_weighted_edges_from({(0, 1, .1), (0, 2, .5), (0, 3, .1), (1, 2, .1),
    ...                            (1, 3, .5), (2, 3, .1)})
    >>> dnx.traveling_salesperson(G, dimod.ExactSolver(), start=0) # doctest: +SKIP
    [0, 1, 2, 3]

    Notes
    -----
    Samplers by their nature may not return the optimal solution. This
    function does not attempt to confirm the quality of the returned
    sample.

    """
    # get lists with all cities
    list_cities = list(G.nodes())

    # Get a QUBO representation of the problem
    Q = dnx.traveling_salesperson_qubo(G, lagrange, weight)

    # use the sampler to find low energy states
    response = sampler.sample_qubo(Q, **sampler_args)
    sample = response.first.sample

    # fill route with None values
    route = [None] * len(G)
    # get cities from sample
    # NOTE: Prevent duplicate city entries by enforcing only one occurrence per city along route
    for (city, time), val in sample.items():
        if val and (city not in route):
            route[time] = city

    # run heuristic replacing None values
    if None in route:
        # get not assigned cities
        cities_unassigned = [city for city in list_cities if city not in route]
        cities_unassigned = list(np.random.permutation(cities_unassigned))
        for idx, city in enumerate(route):
            if city == None:
                route[idx] = cities_unassigned[0]
                cities_unassigned.remove(route[idx])

    # cycle solution to start at provided start location
    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]

    return route
Exemple #11
0
from dwave.system.samplers import DWaveSampler
from dwave.system.composites import EmbeddingComposite
import dimod
import dwave_networkx as dnx

ans = dnx.traveling_salesperson(G, sampler=dimod.ExactSolver(), start=0)
print("ExactSolver [0 1 2 3] ")
print(ans)  #Calculated by Electronic computer

# ------- Set up our QUBO dictionary -------
Q = defaultdict(int)  # Initialize our Q matrix
# Update Q matrix for every edge in the graph
for i, j in G.edges:
    Q[(i, i)] += -1
    Q[(j, j)] += -1
    Q[(i, j)] += 2

# ------- Run our QUBO on the QPU -------
# Set up QPU parameters
chainstrength = 1.0
numruns = 100
Q = dnx.traveling_salesperson_qubo(G)

# Run the QUBO on the solver from your config file
sampler = EmbeddingComposite(DWaveSampler())
d_answer = dnx.traveling_salesperson(G, sampler, start=0)
print("QuantumSolver")
print(d_answer
      )  #Calculated by Quantum Computer or Hybrid Server (Electronic+Quantum)