From 40e84a6cf81108dc9cbfc001a7028e144a025f80 Mon Sep 17 00:00:00 2001 From: Victoria Goliber Date: Tue, 10 Dec 2019 08:46:53 +0900 Subject: [PATCH 1/6] Fix route feasibility check --- dwave_networkx/algorithms/tsp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/algorithms/tsp.py b/dwave_networkx/algorithms/tsp.py index efc31450..c374b3d6 100644 --- a/dwave_networkx/algorithms/tsp.py +++ b/dwave_networkx/algorithms/tsp.py @@ -211,4 +211,4 @@ def is_hamiltonian_path(G, route): """ - return (len(route) == len(set(G))) + return (set(route) == set(G)) From c99b36d66ad752edfe99c2a56421c96c5a2c1f7a Mon Sep 17 00:00:00 2001 From: Victoria Goliber Date: Tue, 10 Dec 2019 09:51:57 +0900 Subject: [PATCH 2/6] Set lagrange parameter if None provided --- dwave_networkx/algorithms/tsp.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dwave_networkx/algorithms/tsp.py b/dwave_networkx/algorithms/tsp.py index c374b3d6..31bfdc2a 100644 --- a/dwave_networkx/algorithms/tsp.py +++ b/dwave_networkx/algorithms/tsp.py @@ -30,7 +30,7 @@ @binary_quadratic_model_sampler(1) -def traveling_salesperson(G, sampler=None, lagrange=2, weight='weight', +def traveling_salesperson(G, sampler=None, lagrange=None, weight='weight', start=None, **sampler_args): """Returns an approximate minimum traveling salesperson route. @@ -117,7 +117,7 @@ def traveling_salesperson(G, sampler=None, lagrange=2, weight='weight', traveling_salesman = traveling_salesperson -def traveling_salesperson_qubo(G, lagrange=2, weight='weight'): +def traveling_salesperson_qubo(G, lagrange=None, weight='weight'): """Return the QUBO with ground states corresponding to a minimum TSP route. If :math:`|G|` is the number of nodes in the graph, the resulting qubo will have: @@ -148,6 +148,9 @@ def traveling_salesperson_qubo(G, lagrange=2, weight='weight'): """ N = G.number_of_nodes() + if lagrange is None: + lagrange = G.size(weight=weight)*G.number_of_nodes()/G.size() + # some input checking if N in (1, 2) or len(G.edges) != N*(N-1)//2: msg = "graph must be a complete graph with at least 3 nodes or empty" From 692667d88cf43c8b9ce9b5643f2bac7382045b36 Mon Sep 17 00:00:00 2001 From: Victoria Goliber Date: Tue, 10 Dec 2019 09:52:52 +0900 Subject: [PATCH 3/6] Update comments and docs --- dwave_networkx/algorithms/tsp.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dwave_networkx/algorithms/tsp.py b/dwave_networkx/algorithms/tsp.py index 31bfdc2a..6a202c7b 100644 --- a/dwave_networkx/algorithms/tsp.py +++ b/dwave_networkx/algorithms/tsp.py @@ -57,7 +57,7 @@ def traveling_salesperson(G, sampler=None, lagrange=None, weight='weight', sampler is provided, one must be provided using the `set_default_sampler` function. - lagrange : number, optional (default 2) + lagrange : number, optional (default None) Lagrange parameter to weight constraints (visit every city once) versus objective (shortest distance route). @@ -130,7 +130,7 @@ def traveling_salesperson_qubo(G, lagrange=None, weight='weight'): G : NetworkX graph A complete graph in which each edge has a attribute giving its weight. - lagrange : number, optional (default 2) + lagrange : number, optional (default None) Lagrange parameter to weight constraints (no edges within set) versus objective (largest set possible). @@ -149,6 +149,7 @@ def traveling_salesperson_qubo(G, lagrange=None, weight='weight'): N = G.number_of_nodes() if lagrange is None: + # if no lagrange parameter provided, set to 'average' tour length lagrange = G.size(weight=weight)*G.number_of_nodes()/G.size() # some input checking From 0600dbb4e7902863e6d104769ee27d2948d50a6e Mon Sep 17 00:00:00 2001 From: Victoria Goliber Date: Tue, 10 Dec 2019 09:55:05 +0900 Subject: [PATCH 4/6] Fix error --- dwave_networkx/algorithms/tsp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/algorithms/tsp.py b/dwave_networkx/algorithms/tsp.py index 6a202c7b..1187e436 100644 --- a/dwave_networkx/algorithms/tsp.py +++ b/dwave_networkx/algorithms/tsp.py @@ -150,7 +150,7 @@ def traveling_salesperson_qubo(G, lagrange=None, weight='weight'): if lagrange is None: # if no lagrange parameter provided, set to 'average' tour length - lagrange = G.size(weight=weight)*G.number_of_nodes()/G.size() + lagrange = G.size(weight=weight)*G.number_of_nodes()/G.number_of_edges() # some input checking if N in (1, 2) or len(G.edges) != N*(N-1)//2: From 0e1bafd2d9ee3d418d056cc2c1b7ea2bba5af67b Mon Sep 17 00:00:00 2001 From: Victoria Goliber Date: Tue, 10 Dec 2019 09:58:13 +0900 Subject: [PATCH 5/6] Fix error --- dwave_networkx/algorithms/tsp.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dwave_networkx/algorithms/tsp.py b/dwave_networkx/algorithms/tsp.py index 1187e436..94988f22 100644 --- a/dwave_networkx/algorithms/tsp.py +++ b/dwave_networkx/algorithms/tsp.py @@ -150,7 +150,10 @@ def traveling_salesperson_qubo(G, lagrange=None, weight='weight'): if lagrange is None: # if no lagrange parameter provided, set to 'average' tour length - lagrange = G.size(weight=weight)*G.number_of_nodes()/G.number_of_edges() + if G.number_of_edges()>0: + lagrange = G.size(weight=weight)*G.number_of_nodes()/G.number_of_edges() + else: + lagrange = 2 # some input checking if N in (1, 2) or len(G.edges) != N*(N-1)//2: From 5fa311c81ff66be8795683f01265a205e4b13591 Mon Sep 17 00:00:00 2001 From: Victoria Goliber Date: Wed, 11 Dec 2019 09:40:37 +0900 Subject: [PATCH 6/6] Add comment on how lagrange value was set --- dwave_networkx/algorithms/tsp.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dwave_networkx/algorithms/tsp.py b/dwave_networkx/algorithms/tsp.py index 94988f22..eedb7ed6 100644 --- a/dwave_networkx/algorithms/tsp.py +++ b/dwave_networkx/algorithms/tsp.py @@ -149,7 +149,10 @@ def traveling_salesperson_qubo(G, lagrange=None, weight='weight'): N = G.number_of_nodes() if lagrange is None: - # if no lagrange parameter provided, set to 'average' tour length + # If no lagrange parameter provided, set to 'average' tour length. + # Usually a good estimate for a lagrange parameter is between 75-150% + # of the objective function value, so we come up with an estimate for + # tour length and use that. if G.number_of_edges()>0: lagrange = G.size(weight=weight)*G.number_of_nodes()/G.number_of_edges() else: