How to emulate a QPU using Qibolab?#

In this section we are going to explain how to setup a platform for pulse emulation and how to use it in Qibolab. To setup a platform we first recommend to have a look at How to connect Qibolab to your lab?.

We are now going to explain a few distinctive features of an emulation platform. All parameters related to the Hamiltonian to be simulated are coded directly in the JSON file under the section configs. Here is an example

{
    "settings": {
        "nshots": 1024,
        "relaxation_time": 0
        },
    "configs": {
        "emulator/bounds": {
        "kind": "bounds",
        "waveforms": 1000000,
        "readout": 50,
        "instructions": 200
        },
    "hamiltonian":{
        "transmon_levels": 2,
        "single_qubit": {
            "0": {
                "frequency": 5e9,
                "anharmonicity": -200e6,
                "t1": {
                    "0-1": 1000
                    },
                "t2": {
                    "0-1": 1900
                    }
                }
            },
        "kind": "hamiltonian"
        },
        "0/drive": {
            "kind": "iq",
            "frequency": 5e9
            },
        "0/drive12": {
            "kind": "iq",
            "frequency": 4.8e9
            },
        "0/probe": {
            "kind": "iq",
            "frequency": 5200000000.0
            },
        "0/acquisition": {
            "kind": "acquisition",
            "delay": 0.0,
            "smearing": 0.0,
            "threshold": 0.0,
            "iq_angle": 0.0,
            "kernel": null
            }
        },
    "native_gates": {
        "single_qubit": {
            "0": {
                "RX": [
                [
                    "0/drive",
                    {
                        "duration": 40,
                        "amplitude": 0.1594,
                        "envelope": {
                            "kind": "gaussian",
                            "rel_sigma": 0.2
                        },
                        "relative_phase": 0.0,
                        "kind": "pulse"
                    }
                ]
                ],
                "RX90": [
                [
                    "0/drive",
                    {
                        "duration": 40,
                        "amplitude": 0.07975,
                        "envelope": {
                            "kind": "gaussian",
                            "rel_sigma": 0.2
                        },
                        "relative_phase": 0.0,
                        "kind": "pulse"
                    }
                ]
                ],
                "MZ": [
                [
                    "0/acquisition",
                    {
                        "kind": "readout",
                        "acquisition": {
                            "kind": "acquisition",
                            "duration": 100.0
                        },
                    "probe": {
                        "duration": 100.0,
                        "amplitude": 0.1,
                        "envelope": {
                            "kind": "gaussian_square",
                            "rel_sigma": 0.2,
                            "width": 0.75
                            },
                        "relative_phase": 0.0,
                        "kind": "pulse"
                    }
                    }
                ]
                ],
                "CP": null
            }
            }
            }
        }

We are defining an Hamiltonian with a transmon with two-levels, with a frequency of \(\omega_q / 2 \pi = 5 \ \text{GHz}\) and anharmoncity \(\alpha/2 \pi = - 200 \ \text{MHz}\), with \(T_1 = 1 \ \mu s\) and \(T_2 = 1.9 \ \mu s\). Everything else follows the usual Qibolab conventions. Keep in mind that you still need to define also a readout pulse even if all parameters ignored in the current emulator except when the readout pulse is played.

We are now going to give an example on how to setup the platform.py file.

# emulator / platform.py


from qibolab import ConfigKinds, IqChannel, Hardware, Qubit
from qibolab.instruments.emulator import EmulatorController, HamiltonianConfig

ConfigKinds.extend([HamiltonianConfig])


def create() -> Hardware:
    """Create an emulator hardware."""
    qubits = {Qubit.default(q) for q in range(1)}
    channels = {
        qubit.drive: IqChannel(mixer=None, lo=None) for qubit in qubits.values()
    }

    # register the instruments
    instruments = {
        "dummy": EmulatorController(address="0.0.0.0", channels=channels),
    }

    return Hardware(
        instruments=instruments,
        qubits=qubits,
    )

We can observe that we need to allocate an object of type EmulatorController where we load the channels. Note that in order to enables the config to support the Hamiltonian configuration we are adding it explicitly in the statement ConfigKinds.extend([HamiltonianConfig]).