Interface

Cirq

trueq.interface.cirq.cirq_to_tq_circ(cirq_circ)

Takes a Cirq Circuit and converts it into a True-Qᵀᴹ Circuit

Note

Measurements are always placed at the end of the circuits.

Parameters

cirq_circ – a Cirq representation of a circuit

Returns

the exact input required by tq_to_cirq_circ(), see that function for a full description of values returned.

Return type

tuple of (Circuit, trueq.interface.metadata.CircMetadata)

trueq.interface.cirq.tq_to_cirq_circ(tq_circ, metadata=None, config='ZXZ', device=None)

Converts a True-Qᵀᴹ Circuit into an Cirq Circuit object.

import cirq
import trueq as tq

mat = cirq.ops.FSimGate(theta=5, phi=1)._unitary_()

fsim_factory = tq.config.GateFactory("fsim", matrix=mat)
x90_factory = tq.config.GateFactory("x", hamiltonian=[["X", 90]])
z_factory = tq.config.GateFactory("z", hamiltonian=[["Z", "phi"]])

config = tq.Config.from_params(
    name="example",
    n_sys=2,
    mode="ZXZXZ",
    factories=[z_factory, x90_factory, fsim_factory],
)

circ = tq.Circuit([{(0, 1): tq.Gate.cx}])

tq.interface.cirq.tq_to_cirq_circ(circ, config=config)

Note

If nothing else is provided, this automatically decomposes single qubit operations into \(R_Z(\theta)R_X(\phi)R_Z(\gamma)\) single qubit gates.

Parameters
  • circuit (Circuit) – A True-Qᵀᴹ circuit to be converted into an Cirq Circuit

  • metadata (trueq.interface.metadata.CirqMetadata) – Metadata required to accurately reproduce the original cirq circuit. If this is not provided, measurements are added at the end of the circuit.

  • config (Config or str) – If a Config which contains gates which are directly decomposable into Cirq native gates is provided, then conversion will take place into gates specified by that config. Additionally config also accepts text strings describing decomposition methods, strings must be of paulis which are defined in trueq.config.decomposition.QubitMode, then Gates are decomposed into all allowed Cirq gates, with single qubit operations being decomposed into the specified pauli string.

  • device (None or cirq.Device) – A cirq.Device, if no device is provided, an unconstrained device with cirq.GridQubit is assumed.

Returns

A Cirq circuit representation of the Circuit

Qiskit

trueq.interface.qiskit.qiskit_dag_to_tq_circ(dag)

Take a qiskit DAG and convert it into a True-Qᵀᴹ Circuit.

Note

Barriers are not preserved, and measurements are always placed at the end of the circuits.

Parameters

dag (qiskit.dagcircuit.DAGCircuit) – a qiskit DAG representation of a circuit

Returns

the exact input required by tq_circ_to_qiskit_circ(), see that function for a full description of values returned.

Return type

tuple of (Circuit, trueq.interface.metadata.QiskitMetadata)

trueq.interface.qiskit.tq_circ_to_qiskit_circ(circuit, metadata=None, config=None)

Converts a True-Qᵀᴹ circuit into an Qiskit DAG object.

Note

If nothing else is provided, this adds measurements on all qubits at the end of the circuit.

Single qubit gates are reduced to the simplest they can up to numerical rounding, IE: some U3 gates become U2 or U1.

Blocking operations are added at the end of every Cycle

Parameters
  • circuit (Circuit) – A TrueQ circuit to be converted into an Qiskit QuantumCircuit

  • metadata (QiskitMetadata) – Metadata required to accurately reproduce the original qiskit circuit. If this is not provided, only 1 quantum register is created, and on classical register, then measurements are added at the end of the circuit mapping each quantum bit to each classical bit.

  • config (Config) – A given config object which contains gates which can be performed by qiskit, but also has hardware restrictions. For example, a Config object can represent a CNOT gate that is restricted to specific sets of qubits, and a CNOT gate is a known native gate in Qiskit. Providing this config means that not only will the circuit be converted into Qiskit representation, but also that it will satisfy hardware restrictions.

Returns

A Qiskit circuit representation of the Circuit

Return type

qiskit.QuantumCircuit

trueq.interface.qiskit.randomly_compile_qiskit(circuit, twirling_group=None, compress=True)

Randomly compiles a given Qiskit QuantumCircuit or DAGCircuit object.

Accepts the same options as trueq.randomly_compile()

Parameters
  • circuit (QuantumCircuit or DAGCircuit) – A Qiskit circuit object

  • twirling_group (dict or None) – A twirling group, see randomized compilation documentation

  • compress (bool) – Whether or not mutable gates should be compressed as much as possible.

Returns

A qiskit circuit

Return type

qiskit.QuantumCircuit

class trueq.interface.qiskit.RCPass(twirling_group=None, compress=True)

This is a Pass object as used in Qiskit’s transpiler object. This enables use of True-Qᵀᴹ’s randomized compilation tools in the framework of Qiskit.

Randomly compile a given DAG, optionally compress single qubit gates as much as possible after insertion of twirl operations.

Beginner users are recommended to use the defaults.

Parameters
  • twirling_group (dict | None) – A twirling group, see randomized compilation documentation

  • compress (bool) – Whether or not mutable gates should be compressed as much as possible.

run(dag)

Randomly Compile a DAGCircuit

Return type

DAGCircuit

trueq.interface.qiskit.get_qiskit_config(skip_1q_static=False)

Gets a trueq.Config which contains all compatable QISKIT gates.

Parameters

skip_1q_static (bool) – If this is True, returned config only contains U1, U2, U3 single qubit gates along with 2 qubit gates. This means H, S, T, etc gates are not present in the config.

Return type

trueq.Config

trueq.interface.qiskit.get_qiskit_transpiler(config=None, rounding=7)

Gets a SubstitutionCompiler which can transpile from arbitrary TrueQ representation of circuits, into a representation which is compatable with qiskit.

This performs a standard set of patterns, and can be used as a template for more advanced compiler definitions.

Parameters
  • config (Config) – A given config object which contains gates which can be performed by qiskit, but also has hardware restrictions. For example, a Config object can represent a CNOT gate that is restricted to specific sets of qubits, and a CNOT gate is a known native gate in Qiskit. Providing this config means that not only will the circuit be converted into Qiskit representation, but also that it will satisfy hardware restrictions.

  • rounding (int) – The number of decimal places to keep in the angles (in degrees) of the KAK decomposition of a two-qubit unitary gate. IE: rounding=0 means that 90.1253 would round to 90, rounding=1 means it would round to 90.1, etc…

Return type

trueq.compilation.SubstitutionCompiler

trueq.interface.qiskit.config_from_backend(backend)

Takes an IBM Backend and converts it into a trueq.Config object.

This works with backends which contain the following gate names, ['u1', 'u2', 'u3', 'cx'].

In the following example, we construct a config object from the “ibmqx2” chip.

import qiskit as qk
import trueq as tq

qk.IBMQ.load_account()
provider = qk.IBMQ.get_provider()
backend = provider.get_backend("ibmqx2")
config = tq.interface.qiskit.config_from_backend(backend)

The config built will contain the chip topology constraints as well as the gates themselves. See trueq.Config for more information.

Parameters

backend (qiskit.provider.BaseBackend) – A backend from qiskit.

Returns

A config which contains gates and topology of a given backend.

Return type

trueq.Config

class trueq.interface.qiskit.Executor(circuits, backend, filename=None, n_shots=1024, max_submissions=25, overwrite=False)

Asynchronous True-Qᵀᴹ circuit submission to a Qiskit backend. This enables submission of large numbers of circuits to a Qiskit backend device.

Since current hardware devices have a limit to the number of circuits that can be run at any one time, batching of circuits must be performed. An example of this is the ibmqx2 chip provided by IBM, it has a stated limit of 75 circuits which may be submitted to it at any one time. This means that if a user wishes to submit more than 75 circuits, the total collection of circuits needs to be broken up into groups (or batches) of no more than 75 circuits. The trueq.CircuitCollection has native support for the batching of circuits like this, and more details can be found under trueq.CircuitCollection.batch().

The Executor converts batched circuits into Qiskit formatted objects, and submits them to the provided backend as jobs on the physical devices. The executor then keeps track of the status of each job asynchronously, updating the status periodically as to where the jobs are in the device’s queue.

Since most devices have a limit as to the number of batches that can be submitted by one user at any given time, the executor will only submit up to a max_submissions number of batches at any one time. Once a batch has run on the device, and has been removed from the job queue, the executor will place another batch into the queue until there are a total of max_submissions submitted jobs at any one time.

Here is a worked example, where a simple circuit is submitted to the IBMQ simulator backend:

import trueq as tq
import qiskit as qk

# loading IBMQ account and selecting a backend
qk.IBMQ.load_account()
provider = qk.IBMQ.get_provider()
backend = provider.get_backend('ibmq_qasm_simulator')

# Generating a simple circuit of only the H gate
circs = tq.Circuit([{0: tq.Gate.h},
                    {0: tq.Meas()}])

# The handling of the submission of the circuits
ex = tq.interface.qiskit.Executor(circs, backend)

# This is a blocking operation, and will block until all data has been acquired
ex.results().results
# [Results({'1': 530, '0': 494})]

A more complicated example, where advanced batching options are used, as well as automatic saving of results:

import trueq as tq
import qiskit as qk

qk.IBMQ.load_account()
provider = qk.IBMQ.get_provider()
backend = provider.get_backend('ibmq_qasm_simulator')

circs = tq.make_srb((0, 1), [4, 64, 128])

# Batch the circuits into groups of 75, including readout calibration circuits
# in each batch
ro_circuits = tq.make_readout_calibration([0,1])
batches = circs.batch(75, extra_circuits=ro_circuits)

ex = tq.interface.qiskit.Executor(batches, backend, filename='example_srb.tq')

ex.results().results
Parameters
  • circuits (trueq.CircuitCollection | trueq.Circuit | generator) –

    The circuits which are to be submitted to the Qiskit backend. Depending on what is submitted here, there are several possible outcomes:

    • trueq.Circuit

      It will be converted to a trueq.CircuitCollection. Results will be placed back inside of the original circuit object itself, and can be viewed as data is retrieved from the backout without having to wait.

    • trueq.CircuitCollection

      It will be batched using the maximum allowed batch size for the given backend. For very long circuits this may result in errors due to limited memory of the classical hardware which control the backend. If errors occur during the submission of a trueq.CircuitCollection, it is recommended to resubmit using the third submission type. Results are placed back inside of the original circuits as data is retrieved from the server.

    • trueq.CircuitCollection.batch

      The circuits will be batched exactly as given by the batch generator. This can be used to submit automatic readout correction circuits, see above example or trueq.CircuitCollection.batch() for more details about possible options. Results are placed inside original circuits as data comes in, note that some batching options may result in additional circuits being added to the collection.

  • backend (qiskit.provider.BaseBackend) – The Qiskit backend where the circuits will be submitted.

  • filename (str) – Optional filename where results will be saved. If this is provided the Executor will also be able to partially recover from a crash of the python session, loss of internet, or other interruption in data acquisition.

  • n_shots (int) – The number of shots of the circuits to be aquired.

  • max_submissions (int) – The maximum number of batches allowed in a backend queue at any one time. A typical IBMQ user has approximately 30 jobs allowed at once. This number is set by the backend provider and should be set here accordingly.

  • overwrite (bool) – Whether to overwrite the file on disk if it exists before these circuits are executed. Note that regardless of the value of this flag, after this first check, the file on disk will continually be updated as new results come in.

property n_shots

Number of shots to be aquired by the backend.

Return type

int

property backend

Qiskit backend where the circuits will be submitted.

Return type

qiskit.provider.BaseBackend

property filename

Filename where circuits with results will be saved.

Return type

str

property circuits

Batched trueq.CircuitCollection, if a single circuit was provided, it will have been converted into a trueq.CircuitCollection. See trueq.interface.qiskit.Executor documentation for more details.

Return type

list

results()

Returns the trueq.CircuitCollection complete with results.

Note

This is a blocking operation, and once called you will have to wait until all circuits have completed acquisition on the backend.

This is not required to be called in order to get results, as results are automatically placed into the provided circuits when they are retrieved from the backend. This function is simply a means to force code to wait until the backend returns all of the results.

Return type

trueq.CircuitCollection

property status

Returns a text representation for the current status of all jobs.

This is a string equivalent of the html output provided in jupyter.

Return type

str

save(overwrite=False)

Saves the current trueq.CircuitCollection regardless of status of acquisition.

This is called automatically whenever a new batch is either submitted or retrieved from the backend.

Parameters

overwrite (bool) – Whether to force an overwrite of the existing file.

cancel()

Cancels all currently submitted jobs if possible.

It is recommended that this be run any time a submission mistake is made, as circuits that have been submitted to the backend will stay in queue otherwise.