Download

Download this file as Jupyter notebook: topology.ipynb.

# Example: Topological Compilation

This example demonstrates how the built-in compiler can be used to ensure that circuits obey the qudit connectivity of a system.

## Connectivity Graphs

Connectivity graphs for our system can be declared through
`Graph`

. We can instantiate custom connectivity
arrangements or use pre-configured systems.

```
[2]:
```

```
import trueq as tq
import trueq.compilation as tqc
import trueq.visualization as tqv
# create an instance of the Regetti Aspen-11 chip.
graph = tqv.Graph.aspen_11(show_labels=True)
graph.plot()
```

## Allocating Labels

We can begin by relabeling our circuit so that their labels match that of our
connectivity graphs using `AllocateLabels`

.

```
[3]:
```

```
circ = tq.Circuit(
[
{(0, 1): tq.Gate.cx},
{(0, 2): tq.Gate.random(4)},
{(0, 3): tq.Gate.cx},
{(0, 4): tq.Gate.random(4)},
]
)
alloc = tqc.AllocateLabels(graph)
circ = tq.Compiler([alloc]).compile(circ)
circ.draw()
```

```
[3]:
```

We see that labels `0, 1, 2, 3, 4`

of our input circuit got respectively mapped to
labels `26, 11, 25, 27, 10`

. `AllocateLabels`

's
remapping attempts to maximize the number of two-qudit gates that act on valid
connections on the targeted graph. In the above example `(26, 11)`

, `(26, 25)`

,
and `(26, 27)`

are all connected on the graph. However, since no qudit in
the Aspen-11 chip contains more than three connections, we cannot make this circuit
obey the couplings through relabeling alone. Therefore the final CNOT gate of
`(26, 10)`

is not valid connection. To ensure that all gates obey the connectivity
we need to also use `DeferredSwapper`

.

## Deferred Swapper

The `DeferredSwapper`

is used to compile circuits so
that every gate obeys the topology of our graph. After relabeling the circuit to
match that of our graph, the Deferred Swapper will insert swaps in order to ensure
that all two-qudit gates are only between labels that can be coupled by the system.

```
[4]:
```

swapper = tqc.DeferredSwapper(graph)
circ = tq.Compiler([swapper]).compile(circ)
circ.draw()

```
[4]:
```

Here the Deferred Swapper inserted swaps before the final Cycle in order to make the
two-qubit gate on `(26, 10)`

valid.
Additionally, this swapping algorithm will combine gates into swap sections where its
optimal to do so. For example:

```
[5]:
```

circ = tq.Circuit([{(26, 10): tq.Gate.random(4)}, {(10, 26): tq.Gate.random(4)}])
circ = tq.Compiler([swapper]).compile(circ)
circ.draw()

```
[5]:
```

Here both of the two-qudit gates get placed in the same opening and closing pair of swap gates.

## Clifford Decomposition

When the Deferred Swapper encounters a `Clifford`

gate,
it may perform a Clifford decomposition when it sees that it is optimal to do so.

```
[6]:
```

```
circ = tq.Circuit([{(26, 10): tq.Gate.cx}])
circ = tq.Compiler([swapper]).compile(circ)
circ.draw()
```

```
[6]:
```

Here, the Deferred Swapper determines that `tq.Gate.cx`

is a Clifford gate and
chooses to decompose it as such. The output is a series of one- and two-qubit
Cliffords gates that obey our graph topology.

Additionally, this Clifford decomposition algorithm can be ran directly by using
`decompose_clifford`

.

Download

Download this file as Jupyter notebook: topology.ipynb.