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()
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()
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
(4): 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()
(4): 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()
Circuit
Key:
No key present in circuit.
     
 
(0): PyQuil.X()
Name:
  • PyQuil.X
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • -1.00j -1.00j
(1): PyQuil.Y()
Name:
  • PyQuil.Y
Aliases:
  • Gate.y
  • Gate.cliff2
Generators:
  • 'Y': 180.0
Matrix:
  • -1.00 1.00
 
imm
(0, 2): PyQuil.CZ()
Name:
  • PyQuil.CZ
Aliases:
  • Gate.cz
Likeness:
  • CNOT
Generators:
  • 'IZ': 90.0
  • 'ZI': 90.0
  • 'ZZ': -90.0
Matrix:
  • 0.71 -0.71j 0.71 -0.71j 0.71 -0.71j -0.71 0.71j
   
 
(1): PyQuil.X()
Name:
  • PyQuil.X
Aliases:
  • Gate.x
  • Gate.cliff1
Generators:
  • 'X': 180.0
Matrix:
  • -1.00j -1.00j
(3): PyQuil.H()
Name:
  • PyQuil.H
Aliases:
  • Gate.h
  • Gate.cliff12
Generators:
  • 'X': 127.279
  • 'Z': 127.279
Matrix:
  • -0.71j -0.71j -0.71j 0.71j
(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()
     ┌───────────────────┐  ░                          ░              ░ ┌─┐   »
q_0: ┤ U3(pi,-pi/2,pi/2) ├──░──■───────────────────────░──────────────░─┤M├───»
     ├───────────────────┴┐ ░  │ ┌───────────────────┐ ░              ░ └╥┘┌─┐»
q_1: ┤ U3(pi,-3pi/2,pi/2) ├─░──┼─┤ U3(pi,-pi/2,pi/2) ├─░──────────────░──╫─┤M├»
     └────────────────────┘ ░  │ └───────────────────┘ ░              ░  ║ └╥┘»
q_2: ───────────────────────░──■───────────────────────░──────────────░──╫──╫─»
                            ░                          ░ ┌──────────┐ ░  ║  ║ »
q_3: ───────────────────────░──────────────────────────░─┤ U2(0,pi) ├─░──╫──╫─»
                            ░                          ░ └──────────┘ ░  ║  ║ »
q_4: ───────────────────────░──────────────────────────░──────────────░──╫──╫─»
                            ░                          ░ ┌──────────┐ ░  ║  ║ »
q_5: ───────────────────────░──────────────────────────░─┤ U1(pi/2) ├─░──╫──╫─»
                            ░                          ░ └──────────┘ ░  ║  ║ »
c_0: ════════════════════════════════════════════════════════════════════╩══╬═»
                                                                            ║ »
c_1: ═══════════════════════════════════════════════════════════════════════╩═»
                                                                              »
c_2: ═════════════════════════════════════════════════════════════════════════»
                                                                              »
c_3: ═════════════════════════════════════════════════════════════════════════»
                                                                              »
c_4: ═════════════════════════════════════════════════════════════════════════»
                                                                              »
«
«q_0: ─────────
«
«q_1: ─────────
«     ┌─┐
«q_2: ┤M├──────
«     └╥┘┌─┐
«q_3: ─╫─┤M├───
«      ║ └╥┘
«q_4: ─╫──╫────
«      ║  ║ ┌─┐
«q_5: ─╫──╫─┤M├
«      ║  ║ └╥┘
«c_0: ═╬══╬══╬═
«      ║  ║  ║
«c_1: ═╬══╬══╬═
«      ║  ║  ║
«c_2: ═╩══╬══╬═
«         ║  ║
«c_3: ════╩══╬═
«            ║
«c_4: ═══════╩═
«              


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

qiskit_circuit.to_trueq()
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): ───────────────────────────Rz(-0.306π)───────────@──────────────Rx(π)──────Rz(-0.306π)───M───
                                                         │                                       │
(1, 0): ────────────────Rx(π)──────Rz(π)─────────Rx(π)───┼───────────────────────────────────────M───
                                                         │                                       │
(2, 0): ───Rz(0.219π)───Rx(0.5π)───Rz(0.5π)──────────────X───Rz(0.5π)───Rx(0.5π)───Rz(-0.219π)───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.131 seconds)

Gallery generated by Sphinx-Gallery