<jupyter_start><jupyter_text>Hybrid Auto and AStar Creates 3 transmon pockets in an L shape, each of which can be rotated in increments of 90 deg.Anchors are user-specified points through which the CPW must pass.For a specified step size and suitable choice of anchors, a snapped path can always be found.How close this path is to the shortest path depends on the step size - a smaller step size generally yields more optimal paths but requires a longer runtime.  Preparations The next cell enables [module automatic reload](https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html?highlight=autoreload). Your notebook will be able to pick up code updates made to the qiskit-metal (or other) module code.<jupyter_code>%load_ext autoreload
%autoreload 2<jupyter_output><empty_output><jupyter_text>Import key libraries and open the Metal GUI. Also we configure the notebook to enable overwriting of existing components<jupyter_code>from qiskit_metal import designs, draw
from qiskit_metal import MetalGUI, Dict

design = designs.DesignPlanar()
gui = MetalGUI(design)

# If you disable the next line, then you will need to delete a component [<component>.delete()] before recreating it.
design.overwrite_enabled = True<jupyter_output><empty_output><jupyter_text>Create 3 transmon qubits with 4 pins. This uses the same definition (options) for all 3 qubits, but it places them in 3 different (x,y) origin points.<jupyter_code>from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket

options = dict(
    pad_width = '425 um', 
    pocket_height = '650um',
    connection_pads=dict(  # pin connectors
        a = dict(loc_W=+1,loc_H=+1), 
        b = dict(loc_W=-1,loc_H=+1, pad_height='30um'),
        c = dict(loc_W=+1,loc_H=-1, pad_width='200um'),
        d = dict(loc_W=-1,loc_H=-1, pad_height='50um')
    )
)

q0 = TransmonPocket(design, 'Q0', options = dict(pos_x='-1.0mm', pos_y='-1.0mm', **options))
q1 = TransmonPocket(design, 'Q1', options = dict(pos_x='1.0mm', pos_y='+0.0mm', **options))
q2 = TransmonPocket(design, 'Q2', options = dict(pos_x='-1.0mm', pos_y='0.0mm', **options))

gui.rebuild()
gui.autoscale()<jupyter_output><empty_output><jupyter_text>Import the RoutePathfinder class and inspect what options are available for you to initialize.<jupyter_code>from qiskit_metal.qlibrary.tlines.pathfinder import RoutePathfinder
RoutePathfinder.get_template_options(design)<jupyter_output><empty_output><jupyter_text>Here we've set the fillet radius to be 90 microns.<jupyter_code>ops=dict(fillet='90um')<jupyter_output><empty_output><jupyter_text>Using the 3-qubit arrangement from before, our goal is to connect pins on two of them. Moreover, we want some degree of control over how that path is constructed.This is where anchors come into play. Anchors are predefined points in space that the path must cross. They are stored in an ordered dictionary data structure that maps theanchor number to a numpy array of length 2. The anchor number is an integer, starting at 0, that determines that anchor point's position relative to the start pin; largeranchor numbers are farther along the path. The numpy array stores the x and y coordinates of the anchor.For this and the subsequent examples, we have chosen a step size of 0.25 mm, which means that the algorithm searches for valid paths to the next anchor point in incrementsof that amount. Valid paths do not collide with other components or self-intersect. The start and end pins are labelled by their component and component-specific pin, inthis case Q0_b and Q1_b.<jupyter_code>import numpy as np
from collections import OrderedDict

anchors = OrderedDict()
anchors[0] = np.array([0.048, -0.555])
anchors[1] = np.array([0.048, 0.195])

options = {'pin_inputs': 
            {'start_pin': {'component': 'Q0', 'pin': 'b'}, 
             'end_pin': {'component': 'Q1', 'pin': 'b'}},
            'lead': {'start_straight': '91um', 'end_straight': '90um'},
            'step_size': '0.25mm',
            'anchors': anchors,
            **ops
           }

qa = RoutePathfinder(design, 'line', options)

gui.rebuild()
gui.autoscale()<jupyter_output><empty_output><jupyter_text>The current algorithm can only allow 1 such CPW to be built at a time, thus we delete old CPWs before building new ones.<jupyter_code>design.delete_component('line')

gui.rebuild()<jupyter_output><empty_output><jupyter_text>Now let's try wrapping the CPW around the outer edge of the bottom left qubit.<jupyter_code>anchors = OrderedDict()
anchors[0] = np.array([-0.452, -0.555])
anchors[1] = np.array([-0.452, -1.5])
anchors[2] = np.array([0.048, -1.5])

options = {'pin_inputs': 
            {'start_pin': {'component': 'Q0', 'pin': 'b'}, 
             'end_pin': {'component': 'Q1', 'pin': 'b'}},
            'lead': {'start_straight': '91um', 'end_straight': '90um'},
            'step_size': '0.25mm',
            'anchors': anchors,
            **ops
           }

qa = RoutePathfinder(design, 'line', options)

gui.rebuild()
gui.autoscale()
design.delete_component('line')

gui.rebuild()<jupyter_output><empty_output><jupyter_text>We can also try switching around the components/pins and not specifying any anchor points to see what happens.<jupyter_code>options = {'pin_inputs': 
            {'start_pin': {'component': 'Q0', 'pin': 'a'}, 
             'end_pin': {'component': 'Q2', 'pin': 'd'}},
            'lead': {'start_straight': '90um', 'end_straight': '90um'},
            'step_size': '0.25mm',
            **ops
          }

qa = RoutePathfinder(design, 'line', options)

gui.rebuild()
gui.autoscale()
design.delete_component('line')

gui.rebuild()<jupyter_output><empty_output><jupyter_text>Or we can specify even more anchor points!<jupyter_code>anchors = OrderedDict()
anchors[0] = np.array([-2, 0.5])
anchors[1] = np.array([0, 0.5])
anchors[2] = np.array([0, -1])
anchors[3] = np.array([2, -1])

options = {'pin_inputs': 
            {'start_pin': {'component': 'Q0', 'pin': 'd'}, 
             'end_pin': {'component': 'Q1', 'pin': 'c'}},
            'step_size': '0.25mm',
            'anchors': anchors,
            **ops
           }

qc = RoutePathfinder(design, 'line', options)

gui.rebuild()
gui.autoscale()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12570145903479238, 'fraction_numerical': 0.02356902356902357, 'mean_word_length': 4.2954159592529715, 'pattern_counts': {'":': 0, '<': 42, '<?xml version=': 0, '>': 42, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '307092', 'license': 'Apache-2.0', 'n_tokens_mistral': 2092, 'n_tokens_neox': 1990, 'n_words': 626, 'path': 'tutorials/2 From components to chip/B. Routing between QComponents/2.13 Hybrid Auto and AStar.ipynb', 'repo_name': 'camponogaraviera/qiskit-metal', 'size': '6237'}