Transpilation

Two common issues that come up when attempting to run an algorithm on specific hardware platforms include:

  1. Gates inside of theoretical circuits are not directly compatible with the hardware’s native gateset.

  2. Gates or circuits are specified as unitary matrices, rather than specific gate decompositions.

If True-Qᵀᴹ has access to the configuration of the system, it is possible to solve both of these issues. Our transpilation tools take a circuit and rewrite it using only the gates and connections specified in a given device configuration file.

../_images/transpilation.svg

Note

The same circuit can be transpiled for implementation on any number of hardware devices. Below we show an example of this.

Transpilation makes use of gate synthesis in order to rewrite a circuit in cycles which are compatible with a given device’s configuration. Synthesis takes a unitary as input and decomposes it into a set of cycles which can be implemented on a specified hardware system, with restrictions specified by the desired platform’s config file.

Other simplifications can be specified for a compiler; the patterns used to rewrite a circuit can be specified by the user, and/or built-in patterns can be leveraged.

Example

#
# Transpiler example.
# Copyright 2019 Quantum Benchmark Inc.
#

import trueq as tq

# Define a device configuration.
config = tq.Config(
    """
    Name: Example
    Mode: ZXZXZ
    Gate Z:
        Hamiltonian:
            - ['Z', 'phi']
    Gate X:
        Hamiltonian:
            - ['X', 'phi']
    Gate CNOT:
        Matrix:
        - [1., 0., 0., 0.]
        - [0., 1., 0., 0.]
        - [0., 0., 0., 1.]
        - [0., 0., 1., 0.]
    """
)

# Make a transpiler based on the device configuration.
transpiler = tq.compilation.get_transpiler(config)

# Define a circuit.
circuit = tq.Circuit([{(0, 1): tq.Gate.swap}])

# Transpile the circuit based on the device.
transpiled_circuit = transpiler.compile(circuit)
print(transpiled_circuit)

Which has the following output:

trueq.Circuit
     (0,): Example.z(phi=-185.2831279678404)   (1,): Example.z(phi=-158.68006046786581) 
     (0,): Example.x(phi=90)                   (1,): Example.x(phi=90)                  
     (0,): Example.z(phi=89.99999999999994)    (1,): Example.z(phi=89.99999999999994)   
     (0,): Example.x(phi=90)                   (1,): Example.x(phi=90)                  
     (0,): Example.z(phi=-269.99999999999994)  (1,): Example.z(phi=-90.00000000000023)  
Imm  (0, 1): Example.cnot()                   
     (0,): Example.z(phi=89.99999999999986)   
     (0,): Example.x(phi=90)                   (1,): Example.x(phi=90)                  
     (0,): Example.z(phi=89.99999999999999)    (1,): Example.z(phi=108.93083918385854)  
     (0,): Example.x(phi=90)                   (1,): Example.x(phi=90)                  
     (0,): Example.z(phi=-101.28212843880362)  (1,): Example.z(phi=-89.99999999999952)  
Imm  (0, 1): Example.cnot()                   
     (0,): Example.z(phi=-78.71787156119632)   (1,): Example.z(phi=-95.58337030367207)  
     (0,): Example.x(phi=90)                   (1,): Example.x(phi=90)                  
     (0,): Example.z(phi=90.00000000000003)    (1,): Example.z(phi=71.152621091832)     
     (0,): Example.x(phi=90)                   (1,): Example.x(phi=90)                  
     (0,): Example.z(phi=21.31993953213363)    (1,): Example.z(phi=-181.80882876294453) 
Imm  (0, 1): Example.cnot()                   
     (0,): Example.z(phi=-90)                 
     (1,): Example.x(phi=90)                  
     (0,): Example.x(phi=90)                   (1,): Example.z(phi=90)                  
     (0,): Example.x(phi=90)                   (1,): Example.x(phi=90)                  
     (0,): Example.z(phi=-180)                 (1,): Example.z(phi=-90)