<jupyter_start><jupyter_text>TUTORIAL FOR TRAVELING SALESMAN PROBLEM __Introduction__: The famous travelling salesman problem (also called the travelling salesperson problem or in short TSP) is a well-known NP-hard problem in combinatorial optimization, asking for the shortest possible route that visits each city exactly once, given a list of cities and the distances between each pair of cities [1]. Applications of the TSP can be found in planning, logistics, and the manufacture of microchips. In these applications, the general concept of a city represents, for example, customers, or points on a chip. __Methods__: Using brute-force search one could try all permutations (ordered combinations) and see which one is cheapest. The running time for this approach, however, lies within a polynomial factor of $O(n!)$, the factorial of the number of cities $n$. Thus, this solution becomes impractical already for only $\sim 20$ cities. Still, many heuristics are known, and some instances with tens of thousands of cities can be solved completely [1]. In this hello-world tutorial we will solve small instances of the TSP with one particular approach, that is simulated annealing and quantum annealing, as made available with D-Wave on Amazon Braket. Specifically, we will leverage two different quantum devices made available through Amazon Braket, namely D-Wave's 2000Q QPU (with 2000 qubits and 6000 couplers) and D-Wave's Advantage QPU (with more than 5000 qubits and more than 35,000 couplers). __TSP as graph problem__: The solution to the TSP can be viewed as a specific ordering of the vertices in a weighted graph.Taking an undirected weighted graph, cities correspond to the graph's nodes, with paths corresponding to the graph's edges, and a path's distance is the edge's weight. Typically, the graph is complete where each pair of nodes is connected by an edge. If no connection exists between two cities, one can add an arbitrarily long edge to complete the graph without affecting the optimal tour [1].The goal is then to find a Hamiltonian cycle with the least weight. We will provide figures for visualization below. __Binary encoding__: To solve the TSP with (quantum) annealing we need to formulate the TSP as a QUBO problem of the general form $$\mathrm{min} \hspace{0.1cm} y=x^{\intercal}Qx + x^{\intercal}B + c,$$ where $x=(x_{1}, x_{2}, \dots)$ is a vector of binary decision variables $x_{i}=0,1$. To this end, here we introduce double-indexed binary variables $x_{i,j}$ with $x_{i,j}=1$ if city $i$is located at position $j$ in the cycle and $x_{i,j}=0$ otherwise. Consider for example three cities: New York indexed with $i=0$, Los Angeles ($i=1$), and Chicago ($i=2$). Then, $x_{0,0}=x_{1,2}=x_{2,1}=1$ means that we visit these cities in the order New York - Chicago - Los Angeles. With this encoding $x_{i,j}$ with $i=0,\dots, N-1$ and $j=0,\dots, N-1$ in total we deal with $N^2$ binary variables for a problem with $N$ cities (nodes in the graph), causing a quadratic overhead.  Our goal is then to find the Hamiltonian cycle with the shortest length, as described by the following objective function$$H_{\mathrm{dist}} = \sum_{i,j} D_{i,j} \sum_{k} x_{i,k}x_{j,k+1},$$with $D_{i,j}$ being the distance between city $i$ and city $j$. Note that the product $x_{i,k}x_{j,k+1}=1$, only if city $i$ is at position $k$ in the cycle and city $j$ is visited right after city $i$; in that case we add the distance $D_{i,j}$ to our objective function which we would like to minimize. Overall, we sum all costs of the distances between successive cities. Finally, we need to account for the following constraints: (i) First, each city should occur exactly once in the cycle. This can be written as: $$\sum_{j=0}^{N-1} x_{i,j}=1 \hspace{0.5cm} \forall i=0,...,N-1.$$(ii) Second, each position in the cycle should be assigned to exactly one city. Mathematically this means:$$\sum_{i=0}^{N-1} x_{i,j}=1 \hspace{0.5cm} \forall j=0,...,N-1.$$For illustration a valid solution for $N=4$ for the route $[1,3,2,4]$ could look as follows (note that every row and column sums up to one, as desired):To enforce solutions that satisfy these constraints we add the following penalty terms to our Hamiltonian$$H_{\mathrm{constraint}} = P \sum_{i=0}^{N-1} \left(1-\sum_{j=0}^{N-1} x_{i,j}\right)^{2} + P \sum_{j=0}^{N-1} \left(1-\sum_{i=0}^{N-1} x_{i,j}\right)^{2}$$With these terms we enforce solutions where every city is visited exactly once as part of the tour. Otherwise, a high penalty value $P$ would be added to the solution, making it unfavorable. For simplicity we use the same penalty parameter $P$ for the two types of constraints covered in $H_{\mathrm{constraint}}$. The total Hamiltonian for the TSP problem then reads$$H = H_{\mathrm{dist}} + H_{\mathrm{constraint}}.$$We will perform hyperparameter optimization on the penalty parameter $P$ in order to find a good solution that complies with the constraints outlined above. If $P$ is not chosen properly it is possible that the algorithm provides solutions that are not acceptable, for example routes that do not cover all cities or routes that visit some cities multiple times. In our code below we apply simple heuristic postprocessing steps to account for these issues.   IMPORTS AND SETUP<jupyter_code>!pip install pandas -q
import boto3
from braket.aws import AwsDevice
from braket.ocean_plugin import BraketSampler, BraketDWaveSampler
import numpy as np
import networkx as nx
import dimod
import dwave_networkx as dnx
from dimod.binary_quadratic_model import BinaryQuadraticModel
from dwave.system.composites import EmbeddingComposite
import matplotlib.pyplot as plt
# magic word for producing visualizations in notebook
%matplotlib inline
from collections import defaultdict
import itertools
import pandas as pd
# local imports
from utils_tsp import get_distance, traveling_salesperson

%load_ext autoreload
%autoreload 2
# Please enter the S3 bucket you created during onboarding in the code below
my_bucket = f"amazon-braket-Your-Bucket-Name" # the name of the bucket
my_prefix = "Your-Folder-Name" # the name of the folder in the bucket
s3_folder = (my_bucket, my_prefix)
# fix random seed for reproducibility
seed = 1
np.random.seed(seed)<jupyter_output><empty_output><jupyter_text>IMPORT DATASET Sample datasets for TSP are available [here](https://people.sc.fsu.edu/~jburkardt/datasets/tsp/tsp.html).Here, we start with a very small dataset comprising five cities only. The minimal tour is known to have length 19.<jupyter_code># load dataset
data = pd.read_csv('tsp_data/five_d.txt', sep='\s+', header=None)
# show data set for inter-city distances
data
# distance between two example cities
idx_city1 = 0
idx_city2 = 1
distance = data[idx_city1][idx_city2]
print('Distance between city {} and city {} is {}.'.format(idx_city1, idx_city2, distance))
# get number of cities
number_cities = data.shape[0]
print('Total number of cities:', number_cities)<jupyter_output>Total number of cities: 5<jupyter_text>SET UP GRAPH We can generate ```networkx``` graphs from ```pandas``` data frames, as explained [here](https://networkx.github.io/documentation/stable/reference/convert.htmlpandas) and in particular [here](https://networkx.github.io/documentation/stable/reference/generated/networkx.convert_matrix.from_pandas_adjacency.html?highlight=from%20pandasnetworkx.convert_matrix.from_pandas_adjacency).<jupyter_code># G = nx.from_pandas_dataframe(data) 
G = nx.from_pandas_adjacency(data)
# pos = nx.random_layout(G) 
pos = nx.spring_layout(G, seed=seed)

# get characteristics of graph
nodes = G.nodes()
edges = G.edges()
weights = nx.get_edge_attributes(G,'weight');
# print weights of graph
print('Weights of graph:', weights)
# show graph with weigths
plt.axis('off'); 
nx.draw_networkx(G, pos, with_labels=True);
nx.draw_networkx_edge_labels(G, pos, edge_labels=weights);<jupyter_output><empty_output><jupyter_text>The weights of this fully-connected graph correspond to the distances between the cities.   QUBO FOR TSP We can get the QUBO matrix using the ```traveling_salesperson_qubo``` method as described [here](https://docs.ocean.dwavesys.com/projects/dwave-networkx/en/latest/reference/algorithms/generated/dwave_networkx.algorithms.tsp.traveling_salesperson_qubo.htmldwave_networkx.algorithms.tsp.traveling_salesperson_qubo).This method will return the QUBO with ground states corresponding to a minimum TSP route.Here, if $|G|$ is the number of nodes (cities) in the original graph, the resulting QUBO will have $|G|^2$ variables/nodesand $|G|^2(|G|^2-1)/2$ edges. There is a quadratic overhead because of the binary encoding $x_{i,j}=1$ if city $i$ is at position $j$ on the route and zero otherwise. The Lagrange penalty parameter enforces the constraints that every city should be visited exactly once in our route (i.e., we do not leave out any city and we do not visit cities multiple times). As this parameter can be tuned we will run hyperparameter optimization (HPO) to find a good value for this hyperparameter.<jupyter_code># get QUBO for TSP
tsp_qubo = dnx.algorithms.tsp.traveling_salesperson_qubo(G)
# find default Langrange parameter for enforcing constraints

# set parameters
lagrange = None
weight='weight'

# get corresponding QUBO step by step
N = G.number_of_nodes()

if lagrange is None:
    # 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:
        lagrange = 2

print('Default Lagrange parameter:', lagrange)   
# create list around default value for HPO 
lagrange_list= list(np.arange(int(0.8*lagrange), int(1.1*lagrange)))
print('Lagrange parameter for HPO:', lagrange_list)<jupyter_output>Lagrange parameter for HPO: [19, 20, 21, 22, 23, 24, 25]<jupyter_text>SOLUTION WITH SIMULATED ANNEALING First let us solve the TSP problem with classical simulated annealing.To this end we can simply call the built-in ```traveling_salesperson(...)``` routine from the ```dwave_networkx``` package using the ```SimulatedAnnealingSampler``` sampler as provided in the standard Ocean tool suite.<jupyter_code># use (classical) simulated annealing
sampler = dimod.SimulatedAnnealingSampler()
# route = dnx.traveling_salesperson(G, dimod.ExactSolver(), start=0)
route = dnx.traveling_salesperson(G, sampler, start=0)
print('Route found with simulated annealing:', route)
# get the total distance
total_dist = 0
for idx, node in enumerate(route[:-1]):
    dist = data[route[idx+1]][route[idx]]
    total_dist += dist

print('Total distance (without return):', total_dist)
# add distance between start and end point to complete cycle
return_distance = data[route[0]][route[-1]]
print('Distance between start and end:', return_distance)
# get distance for full cyle 
distance = total_dist + return_distance
print('Total distance (including return):', distance)<jupyter_output>Total distance (including return): 19.0<jupyter_text>SOLUTION WITH QUANTUM ANNEALING ON D-WAVE WITH HPO FOR LAGRANGE PARAMETER Now let us run the TSP problem on D-Wave's 2000Q QPU, together with hyperparameter optimization for the Langrange parameter.To this end, we augment the ```traveling_salesperson(...)``` routine with post-processing heuristics that correct for invalid solutions if some cities are not present in the sample produced by D-Wave or if some cities are duplicates in the route. The original source code for ```traveling_salesperson(...)``` can be found in the Appendix.<jupyter_code># run TSP with imported TSP routine
sampler = BraketDWaveSampler(s3_folder,'arn:aws:braket:::device/qpu/d-wave/DW_2000Q_6')
sampler = EmbeddingComposite(sampler)

# set parameters
num_shots = 1000
start_city = 0
best_distance = sum(weights.values())
best_route = [None]*len(G)

# run HPO to find route
for lagrange in lagrange_list:
    print('Running quantum annealing for TSP with Lagrange parameter=', lagrange)
    route = traveling_salesperson(G, sampler, lagrange=lagrange, 
                                  start=start_city, num_reads=num_shots, answer_mode="histogram")
    # print route 
    print('Route found with D-Wave:', route)
    
    # print distance
    total_dist, distance_with_return = get_distance(route, data)
    
    # update best values
    if distance_with_return < best_distance:
        best_distance = distance_with_return
        best_route = route

print('---FINAL SOLUTION---')
print('Best solution found with D-Wave:', best_route)
print('Total distance (including return):', best_distance)<jupyter_output>Running quantum annealing for TSP with Langrgange parameter= 19
Route found with D-Wave: [0, 2, 1, 4, 3]
Total distance (without return): 17.0
Total distance (including return): 19.0
Running quantum annealing for TSP with Langrgange parameter= 20
Route found with D-Wave: [0, 3, 4, 1, 2]
Total distance (without return): 15.0
Total distance (including return): 19.0
Running quantum annealing for TSP with Langrgange parameter= 21
Route found with D-Wave: [0, 3, 4, 1, 2]
Total distance (without return): 15.0
Total distance (including return): 19.0
Running quantum annealing for TSP with Langrgange parameter= 22
Route found with D-Wave: [0, 3, 4, 1, 2]
Total distance (without return): 15.0
Total distance (including return): 19.0
Running quantum annealing for TSP with Langrgange parameter= 23
Route found with D-Wave: [0, 2, 1, 4, 3]
Total distance (without return): 17.0
Total distance (including return): 19.0
Running quantum annealing for TSP with Langrgange parameter= 24
Route found with D-Wa[...]<jupyter_text>Now let us visualize the solution found by the D-Wave QPU. First we plot again the original graph with nodes representing cities and weighted edges representing distances between the cities. It is a complete graph showing the distance for every pair of cities. Then, we plot below the graph showing the proposed route, with steps labelling the specific sequence connecting the individual stops on the route.<jupyter_code># show original graph with weigths
plt.axis('off'); 
nx.draw_networkx(G, pos, with_labels=True, font_color='w');
nx.draw_networkx_edge_labels(G, pos, edge_labels=weights);
# get mapping from original nodes to position in cycle
node_labels = {list(nodes)[ii]: best_route[ii] for ii in range(number_cities)}
# Construct route as list of (node_i, node_i+1)
sol_graph_base = [(best_route[idx], best_route[idx+1]) for idx in range(len(best_route)-1)]
# Establish weights between nodes along route, allowing for mirrored keys (i.e. weights[(0, 1)] = weights[(1, 0)])
best_weights = {k: weights[k] if k in weights.keys() else weights[(k[1],k[0])] for k in sol_graph_base}
# Rebuild graph containing only route connections
G_best = nx.Graph(sol_graph_base)

route_labels = {x: f'step_{i}={best_weights[x]}' for i, x in enumerate(sol_graph_base)}
# show solution
plt.axis('off'); 
nx.draw_networkx(G_best, pos, font_color='w');
nx.draw_networkx_edge_labels(G_best, pos, edge_labels=route_labels, label_pos=0.25);<jupyter_output><empty_output><jupyter_text>In conclusion, in this part of our tutorial we have solved a very small instance of the famous NP-hard TSP problem using both (classical) simulated annealing and quantum annealing using D-Wave's Ocean tool suite that is natively supported on Amazon Braket. While there are classical methods that can solve this problem very efficiently, at least to a very good approximation, this is an educational tutorial focused on the formulation of a specific QUBO problem and the approximate solution thereof using (quantum) annealing methods. Below we extend our analysis to larger problem sizes that cannot be embedded on the 2000Q D-Wave chip with Chimera connectivity, but can be run on the larger Advantage chip with $\sim 5000$ physical variables and Pegasus connectivity.   LARGER TSP PROBLEM ON D-WAVE ADVANTAGE CHIP Next we run a larger problem instance of TSP on D-Wave's Advantage chip with over 5000 physical qubits and Pegasus connectivity graph. We take a dataset comprising ten cities; we have taken the original data set with 15 cities from [here](https://people.sc.fsu.edu/~jburkardt/datasets/tsp/tsp.html) and cut it down to a smaller dataset containing only the first ten cities. First let us load and inspect the data set for the inter-city distances.<jupyter_code># load dataset
data10 = pd.read_csv('tsp_data/data10cities.csv')
# rename columns from object to int 
dic_map = {}
for key in data10.columns:
    d = {key: int(key)}
    dic_map.update(d)
data10 = data10.rename(columns=dic_map)
# show data set for inter-city distances
data10<jupyter_output><empty_output><jupyter_text>Next, using the ```networkx``` library again we display this problem as a complete graph with a single node per city and weighted edges specifying the intercity distances.<jupyter_code># G = nx.from_pandas_dataframe(data) 
G = nx.from_pandas_adjacency(data10)
# pos = nx.random_layout(G) 
pos = nx.spring_layout(G, seed=seed)

# get characteristics of graph
nodes = G.nodes()
edges = G.edges()
weights = nx.get_edge_attributes(G,'weight');

# show graph with weigths
plt.figure(figsize=(10,10))
plt.axis('off'); 
nx.draw_networkx(G, pos, with_labels=True);
nx.draw_networkx_edge_labels(G, pos, edge_labels=weights, label_pos=0.25);<jupyter_output><empty_output><jupyter_text>Now that the problem is set up as a graph problem, we first use classical simulated annealing to easily build a classical benchmark, using the ```SimulatedAnnealingSampler``` that comes out of the box with the ```dimod``` library.<jupyter_code># use (classical) simulated annealing
sampler = dimod.SimulatedAnnealingSampler()
# route = dnx.traveling_salesperson(G, dimod.ExactSolver(), start=0)
route = dnx.traveling_salesperson(G, sampler, start=0)
print('Route found with simulated annealing:', route)
# print distance
total_dist, distance_with_return = get_distance(route, data10)<jupyter_output>Total distance (without return): 310
Total distance (including return): 378<jupyter_text>Below again we will run HPO to try several numerical values for the hyperparameter $P$ enforcing the constraints within the cost function.To this end we first set up a list of parameters to loop over later in our simulation routine.<jupyter_code># find default Langrange parameter for enforcing constraints

# set parameters
lagrange = None
weight='weight'

# get corresponding QUBO step by step
N = G.number_of_nodes()

if lagrange is None:
    # 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:
        lagrange = 2

print('Default Lagrange parameter:', lagrange)   
# create list around default value for HPO 
# lagrange_list= list(np.arange(int(0.99*lagrange), int(1.01*lagrange)))
lagrange_list= [int(lagrange)-10, int(lagrange), int(lagrange)+10]
print('Lagrange parameter for HPO:', lagrange_list)<jupyter_output>Lagrange parameter for HPO: [428, 438, 448]<jupyter_text>Next, we try to run this problem on D-Wave's 2000Q backend with Chimera connectivity. Here, we will run into an ```ValueError: no embedding found```, because a problem with 10 cities results in a fully-connected problem with 100 logical variables. This problem size cannot be embedded onto the sparse Chimera graph with $\sim 2000$ physical qubits. Therefore we will try to run the same problem on the larger Advantage chip below.<jupyter_code># run TSP on 2000Q chip
sampler = BraketDWaveSampler(s3_folder,'arn:aws:braket:::device/qpu/d-wave/DW_2000Q_6')
sampler = EmbeddingComposite(sampler)

# set parameters
num_shots = 1000
start_city = 0

try: 
    print('Running quantum annealing for TSP with Lagrange parameter=', lagrange)
    route = traveling_salesperson(G, sampler, lagrange=lagrange_list[0], 
                                  start=start_city, num_reads=num_shots, answer_mode="histogram")
    # print route 
    print('Route found with D-Wave:', route)
except ValueError:
    print("ValueError: no embedding found. This problem is too large to be embedded on the 2000Q chip.")<jupyter_output>Running quantum annealing for TSP with Langrgange parameter= 438.0
ValueError: no embedding found. This problem is too large to be embedded on the 2000Q chip.<jupyter_text>Next we simply switch to the D-Wave's Advantage chip with over 5000 physical qubits and Pegasus connectivity graph. This switch amounts to changing one line of code.<jupyter_code># run TSP on Advantage chip
sampler = BraketDWaveSampler(s3_folder,'arn:aws:braket:::device/qpu/d-wave/Advantage_system4')
sampler = EmbeddingComposite(sampler)

# set parameters
num_shots = 1000
start_city = 0
best_distance = sum(weights.values())
best_route = [None]*len(G)

# run HPO to find route
for lagrange in lagrange_list:
    print('Running quantum annealing for TSP with Lagrange parameter=', lagrange)
    route = traveling_salesperson(G, sampler, lagrange=lagrange, 
                                  start=start_city, num_reads=num_shots, answer_mode="histogram")
    # print route 
    print('Route found with D-Wave:', route)
    
    # print distance
    total_dist, distance_with_return = get_distance(route, data10)
    
    # update best values
    if distance_with_return < best_distance:
        best_distance = distance_with_return
        best_route = route

print('---FINAL SOLUTION---')
print('Best solution found with D-Wave:', best_route)
print('Total distance (including return):', best_distance)<jupyter_output>Running quantum annealing for TSP with Langrgange parameter= 428
Route found with D-Wave: [0, 1, 7, 2, 6, 4, 5, 8, 9, 3]
Total distance (without return): 341
Total distance (including return): 387
Running quantum annealing for TSP with Langrgange parameter= 438
Route found with D-Wave: [0, 2, 1, 9, 5, 7, 3, 4, 8, 6]
Total distance (without return): 379
Total distance (including return): 451
Running quantum annealing for TSP with Langrgange parameter= 448
Route found with D-Wave: [0, 7, 2, 6, 4, 8, 1, 3, 9, 5]
Total distance (without return): 294
Total distance (including return): 346
---FINAL SOLUTION---
Best solution found with D-Wave: [0, 7, 2, 6, 4, 8, 1, 3, 9, 5]
Total distance (including return): 346<jupyter_text>In conclusion in this tutorial we have mapped the canonical TSP to a QUBO problem using the Ocean tool suite that is natively supported on Amazon Braket. We have used classical simulated annealing and quantum annealing to find solutions to this problem. Specifically, we have seen that we can solve larger problem instances with the Advantage chip (that has more than 5000 qubits and more than 35,000 couplers) than what we could solve for using the previous-generation 2000Q QPU with roughly 2000 qubits and 6000 couplers.  --- APPENDIX  APPENDIX FOR HEURISTIC POSTPROCESSING If there are cities unassigned to route, we just fill the route with these without optimization. First, we can take care of filling ```None``` values.<jupyter_code># set example route
route = [None, 4, 0, 3, 1]
print('Original route:', route)
# get lists with all cities
list_cities = list(nodes)
# get not assigned cities
cities_unassigned = [city for city in list_cities if city not in route] 
# fill None values
for idx, city in enumerate(route):
    if city == None:
        route[idx] = cities_unassigned[0]
        cities_unassigned.remove(route[idx])
print('Route after filling heuristic:', route)
# randomly permute
cities_unassigned = [0, 4, 7]
np.random.permutation(cities_unassigned)<jupyter_output><empty_output><jupyter_text>Second, we can still have proposed routes with cities appearing multiple times in exchange for some cities not visited at all.<jupyter_code># set example route
route = [0, 2, 3, 4, 4]
print('Original route:', route)
unique_entries = set(route)
number_unique_entries = len(unique_entries)
if number_unique_entries != len(route):
    print('Solution not valid.')
# get unassigned cities
cities_unassigned = [city for city in list_cities if city not in route]
print('Unassigned cities:', cities_unassigned)

# replace duplicates
route_new = []
for city in route:
    if city not in route_new:
        route_new.append(city)
    else:
        route_new.append(cities_unassigned[0])
        cities_unassigned.remove(route_new[-1])
print('Route after heuristics:', route_new)
# set example route
route = [0, 0, 1, 1, 1]
print('Original route:', route)
unique_entries = set(route)
number_unique_entries = len(unique_entries)
if number_unique_entries != len(route):
    print('Solution not valid.')
# get unassigned cities
cities_unassigned = [city for city in list_cities if city not in route]
print('Unassigned cities:', cities_unassigned)

# replace duplicates
route_new = []
for city in route:
    if city not in route_new:
        route_new.append(city)
    else:
        route_new.append(cities_unassigned[0])
        cities_unassigned.remove(route_new[-1])
print('Route after heuristics:', route_new)<jupyter_output>Original route: [0, 0, 1, 1, 1]
Solution not valid.
Unassigned cities: [2, 3, 4, 5, 6, 7, 8, 9]
Route after heuristics: [0, 2, 1, 3, 4]
{'fraction_non_alphanumeric': 0.08933197268231416, 'fraction_numerical': 0.01935002747468404, 'mean_word_length': 5.138039026740544, 'pattern_counts': {'":': 0, '<': 54, '<?xml version=': 0, '>': 54, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '4693', 'license': 'Apache-2.0', 'n_tokens_mistral': 8027, 'n_tokens_neox': 7380, 'n_words': 3067, 'path': 'examples/quantum_annealing/Dwave_TravelingSalesmanProblem/Dwave_TravelingSalesmanProblem.ipynb', 'repo_name': 'dumplingsforbreakfast/amazon-braket-examples', 'size': '25478'}