Interface: Introduction

In this example, we demonstrate how to convert between the True-Q™ python circuit representation and other popular third party representations. These conversions will only be available if the corresponding python packages are installed.

We start by defining a test circuit to work with:

import trueq as tq

circuit = tq.Circuit(
    [
        {(0,): tq.Gate.x, (1,): tq.Gate.y},
        {(0, 2): tq.Gate.cz, (1,): tq.Gate.x},
        {(3,): tq.Gate.h, (5,): tq.Gate.s},
    ]
)
circuit.measure_all()
True-Q formatting will not be loaded without trusting this notebook or rerunning the affected cells. Notebooks can be marked as trusted by clicking "File -> Trust Notebook".
Circuit
Key:
No key present in circuit.
         
 
(0): Gate.x
Name:
  • Gate.x
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • 1.00 1.00
(1): Gate.y
Name:
  • Gate.y
Aliases:
  • Gate.y
  • Gate.cliff2
Generators:
  • 'Y': 180.0
Matrix:
  • -1.00j 1.00j
     
imm
(0, 2): Gate.cz
Name:
  • Gate.cz
Aliases:
  • Gate.cz
Likeness:
  • CNOT
Generators:
  • 'IZ': 90.0
  • 'ZI': 90.0
  • 'ZZ': -90.0
Matrix:
  • 1.00 1.00 1.00 -1.00
(1): Gate.x
Name:
  • Gate.x
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • 1.00 1.00
     
 
(3): Gate.h
Name:
  • Gate.h
Aliases:
  • Gate.h
  • Gate.cliff12
Generators:
  • 'X': 127.279
  • 'Z': 127.279
Matrix:
  • 0.71 0.71 0.71 -0.71
(5): Gate.s
Name:
  • Gate.s
Aliases:
  • Gate.s
  • Gate.cliff9
Generators:
  • 'Z': 90.0
Matrix:
  • 0.71 -0.71j 0.71 0.71j
     
imm
(0): Meas()
Name:
  • Meas()
(1): Meas()
Name:
  • Meas()
(2): Meas()
Name:
  • Meas()
(3): Meas()
Name:
  • Meas()
(5): Meas()
Name:
  • Meas()


Cirq

Convert the circuit to a Cirq circuit object:

cirq_circuit = circuit.to_cirq()
cirq_circuit
               ┌──┐
(0, 0): ───X────@─────────M───
                │         │
(1, 0): ───Y────┼X────────M───
                │         │
(2, 0): ────────@─────────M───
                          │
(3, 0): ──────────────H───M───
                          │
(5, 0): ──────────────S───M───
               └──┘


Perform the inverse conversion (to_trueq() is monkey-patched onto their circuit object at True-Q™ import time):

cirq_circuit.to_trueq()
True-Q formatting will not be loaded without trusting this notebook or rerunning the affected cells. Notebooks can be marked as trusted by clicking "File -> Trust Notebook".
Circuit
Key:
No key present in circuit.
         
 
(0): Gate.x
Name:
  • Gate.x
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • 1.00 1.00
(1): Gate.y
Name:
  • Gate.y
Aliases:
  • Gate.y
  • Gate.cliff2
Generators:
  • 'Y': 180.0
Matrix:
  • -1.00j 1.00j
     
imm
(0, 2): Gate.cz
Name:
  • Gate.cz
Aliases:
  • Gate.cz
Likeness:
  • CNOT
Generators:
  • 'IZ': 90.0
  • 'ZI': 90.0
  • 'ZZ': -90.0
Matrix:
  • 1.00 1.00 1.00 -1.00
(1): Gate.x
Name:
  • Gate.x
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • 1.00 1.00
     
 
(3): Gate.h
Name:
  • Gate.h
Aliases:
  • Gate.h
  • Gate.cliff12
Generators:
  • 'X': 127.279
  • 'Z': 127.279
Matrix:
  • 0.71 0.71 0.71 -0.71
(5): Gate.s
Name:
  • Gate.s
Aliases:
  • Gate.s
  • Gate.cliff9
Generators:
  • 'Z': 90.0
Matrix:
  • 1.00 1.00j
     
 
(0): Meas()
Name:
  • Meas()
(1): Meas()
Name:
  • Meas()
(2): Meas()
Name:
  • Meas()
(3): Meas()
Name:
  • Meas()
(5): Meas()
Name:
  • Meas()


PyQuil

Convert the circuit to a PyQuil circuit object:

pyquil_circuit = circuit.to_pyquil()
print(pyquil_circuit)

Out:

DECLARE ro BIT[5]
X 0
Y 1
CZ 0 2
X 1
H 3
S 5
MEASURE 0 ro[0]
MEASURE 1 ro[1]
MEASURE 2 ro[2]
MEASURE 3 ro[3]
MEASURE 5 ro[4]

Perform the inverse conversion (to_trueq() is monkey-patched onto their circuit object at True-Q™ import time):

pyquil_circuit.to_trueq()
True-Q formatting will not be loaded without trusting this notebook or rerunning the affected cells. Notebooks can be marked as trusted by clicking "File -> Trust Notebook".
Circuit
Key:
No key present in circuit.
     
       
 
(0): PyQuil.X()
Name:
  • PyQuil.X
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • 1.00 1.00
(1): PyQuil.Y()
Name:
  • PyQuil.Y
Aliases:
  • Gate.y
  • Gate.cliff2
Generators:
  • 'Y': 180.0
Matrix:
  • -1.00j 1.00j
 
imm
(0, 2): PyQuil.CZ()
Name:
  • PyQuil.CZ
Aliases:
  • Gate.cz
Likeness:
  • CNOT
Generators:
  • 'IZ': 90.0
  • 'ZI': 90.0
  • 'ZZ': -90.0
Matrix:
  • 1.00 1.00 1.00 -1.00
   
       
       
 
(1): PyQuil.X()
Name:
  • PyQuil.X
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • 1.00 1.00
(3): PyQuil.H()
Name:
  • PyQuil.H
Aliases:
  • Gate.h
  • Gate.cliff12
Generators:
  • 'X': 127.279
  • 'Z': 127.279
Matrix:
  • 0.71 0.71 0.71 -0.71
(5): PyQuil.S()
Name:
  • PyQuil.S
Aliases:
  • Gate.s
  • Gate.cliff9
Generators:
  • 'Z': 90.0
Matrix:
  • 0.71 -0.71j 0.71 0.71j


Qiskit

Convert the circuit to a Qiskit circuit object:

qiskit_circuit = circuit.to_qiskit()
qiskit_circuit.draw("mpl")
interface software

Out:

<Figure size 1290.83x618.722 with 1 Axes>

Perform the inverse conversion (to_trueq() is monkey-patched onto their circuit object at True-Q™ import time):

qiskit_circuit.to_trueq()
True-Q formatting will not be loaded without trusting this notebook or rerunning the affected cells. Notebooks can be marked as trusted by clicking "File -> Trust Notebook".
Circuit
Key:
No key present in circuit.
         
 
(0): Gate.x
Name:
  • Gate.x
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • -1.00j -1.00j
(1): Gate.y
Name:
  • Gate.y
Aliases:
  • Gate.y
  • Gate.cliff2
Generators:
  • 'Y': 180.0
Matrix:
  • -1.00j 1.00j
     
imm
(0, 2): Gate.cz
Name:
  • Gate.cz
Aliases:
  • Gate.cz
Likeness:
  • CNOT
Generators:
  • 'IZ': 90.0
  • 'ZI': 90.0
  • 'ZZ': -90.0
Matrix:
  • 1.00 1.00 1.00 -1.00
(1): Gate.x
Name:
  • Gate.x
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • -1.00j -1.00j
     
 
(3): Gate.h
Name:
  • Gate.h
Aliases:
  • Gate.h
  • Gate.cliff12
Generators:
  • 'X': 127.279
  • 'Z': 127.279
Matrix:
  • 0.71 0.71 0.71 -0.71
(5): Gate.s
Name:
  • Gate.s
Aliases:
  • Gate.s
  • Gate.cliff9
Generators:
  • 'Z': 90.0
Matrix:
  • 1.00 1.00j
     
 
(0): Meas()
Name:
  • Meas()
(1): Meas()
Name:
  • Meas()
(2): Meas()
Name:
  • Meas()
(3): Meas()
Name:
  • Meas()
(5): Meas()
Name:
  • Meas()


Priority Lists

During conversion between representations in True-Q™ and other software packages, there is often a degeneracy in how a gate can be represented. For example, an identity gate could be written as Z(phi), X(phi), Y(phi), … with phi = 0.

In these cases, the priority list associated with the interface to a software package will handle the degeneracy by converting preferentially to gates which appear higher on the priority list.

Each interface has a default priority list and corresponding configuration file preset. To update a priority list and configuration file (using Cirq as an example), users can provide a priority list via set_priority_list() and retrieve the current priority list via get_config(). Replacing cirq in these commands with pyquil or qiskit will interact in the same way with their corresponding interfaces.

Look at the priority list for the interface between True-Q™ and Cirq:

tq.interface.cirq.get_priority_list()

Out:

['I', 'X', 'Y', 'Z', 'H', 'S', 'T', 'CZ', 'CNOT', 'XX', 'YY', 'ZZ', 'ISWAP', 'SWAP', 'rx', 'ry', 'rz', 'FSimGate', 'ms', 'PhasedXPowGate']

Set a limited priority list, containing only CNOT, rx, and rz:

tq.interface.cirq.set_priority_list(["CNOT", "rx", "rz"])

Convert the circuit defined above to Cirq using the updated priority list:

circuit.to_cirq()
(0, 0): ───Rx(-π)───────────────────────Rz(-0.5π)───@─────────────────────────Rz(0.5π)────────────────────────────────────M───
                                                    │                                                                     │
(1, 0): ───Rx(-π)───Rz(-π)──────────────────────────┼──────────────Rx(-π)─────────────────────────────────────────────────M───
                                                    │                                                                     │
(2, 0): ─────────────────────Rx(0.5π)───Rz(0.5π)────X───Rz(0.5π)───Rx(0.5π)───Rz(-π)──────────────────────────────────────M───
                                                                                                                          │
(3, 0): ─────────────────────────────────────────────────────────────────────────────────Rz(0.5π)───Rx(0.5π)───Rz(0.5π)───M───
                                                                                                                          │
(5, 0): ───────────────────────────────────────────────────────────────────────────────────────────────────────Rz(0.5π)───M───


Note

Setting the priority list to None resets to the default priority list.

Reset the priority list to the default:

tq.interface.cirq.set_priority_list(None)

Convert the circuit to Cirq using the default priority list:

circuit.to_cirq()
               ┌──┐
(0, 0): ───X────@─────────M───
                │         │
(1, 0): ───Y────┼X────────M───
                │         │
(2, 0): ────────@─────────M───
                          │
(3, 0): ──────────────H───M───
                          │
(5, 0): ──────────────S───M───
               └──┘


As you can see in the printed circuits, changing the priority list alters the gates used in converting from True-Q™ to other software. For example, removing the X gate from the priority list causes the interface to pick the next viable representation of this operation, so that the X gates are given as rotations about X by \(\pi\).

Total running time of the script: ( 0 minutes 0.377 seconds)

Gallery generated by Sphinx-Gallery