Quantum-circuit to quantum-device layer compilation backend

Explanation of changes

This merge request creates a new more general compilation backend for the quantum-circuit to quantum-device compilation.

  • it replaces the add_pulse_information_transmon that has been marked as deprecated the old code is still functional for backwards compatibility (closes #64 (closed)).
  • it creates a new structure for the configuration files based on the pydantic datastructure introduced in !341 (merged) ( closing #67 (closed)).
  • support for the new configuration files has been added to the QuantumDevice and TransmonElement. A future version will need to redesign the Transmon Element to make the structure of the parameters match the structure of the configuration files and result in a better UX.

This new configuration allows users to easily use custom (user-defined) pulses or gates, without needing to program a new compiler backend. This is a priority as this functionality is required for several projects.

This MR has tests and an example configuration and all data structures have appropriate docstrings.

Immediate further work would

  • modify the user-guide to explain how to use this (in combination with the QuantumDevice and TransmonElement)
  • expand the user-guide to explain how to use this with custom operations (and custom device objects) (separate MR/issue?).
  • provide an example "edge" that can be added to the QuantumDevice (separate MR/issue).

Merge checklist

See also merge request guidelines

  • Merge request has been reviewed and approved by a project maintainer.
  • Merge request contains a clear description of the proposed changes and the issue it addresses.
  • Merge request made onto appropriate branch (develop for most MRs).
  • New code is fully tested.
  • New code is documented and docstrings use numpydoc format.
  • CHANGELOG.rst and AUTHORS.rst have been updated (when applicable).
  • CI pipelines pass
    • pre-commit run --all-files --hook-stage commit passes (gitlab-ci),
    • test suite passes (gitlab-ci),
    • no degradation in code-coverage (codacy),
    • no (serious) new pylint code quality issues introduced (codacy),
    • documentation builds successfully (CI and readthedocs),
    • windows tests pass (manually triggered by maintainers before merging).

THIS IS OLD TEXT

Although I have added tests and an example configuration, this MR cannot be merged yet.

Before this can be merged, the following needs to happen

  • a tutorial, explaining how a user can create a custom configuration and how to use this.
  • make the existing transmon element generate a config in the new style to allow depreciation without breaking existing code. (still requires some bugfixes found in test).
  • add pydantic based validators (allow schema validation without breaking backwards compatibility).
  • documentation for the configuration format, potentially including a python object to validate configurations (traitlets, pydantic, json-schema, not sure what's best yet).
  • documentation on what a valid generator function is and how this helps with composite and/or parameterized operations.

An important consideration for keeping the new configs as simple dictionaries is that that is something I can easily explain to a user. More complex objects could also work, but I'm a bit hesitant to start making a custom data structure (although we might create such a thing from a dictionary representation).

Structure of config files

sched = Schedule("Test schedule")

# define the resources
# q0, q1 = Qubits(n=2) # assumes all to all connectivity
q0, q1 = ("q0", "q1")
sched.add(Reset(q0, q1))

sched.add(Rxy(90, 0, qubit=q0))
sched.add(Rxy(180, 0, qubit=q1), ref_pt='start')
sched.add(CZ(qC=q0, qT=q1))
sched.add(Rxy(theta=90, phi=0, qubit=q0))
sched.add(Measure(q0, q1), label="M0")

# pulse information is added
dev_sched = add_pulse_information_transmon(
    deepcopy(sched), device_cfg=DEVICE_CONFIG_OLD
)

new_dev_sched = compile_circuit_to_device(sched, device_cfg=example_transmon_cfg)
new_dev_sched = determine_absolute_timing(schedule=new_dev_sched, time_unit="physical")

image

image

example_transmon_cfg = {
    "backend": "quantify_scheduler.backends.circuit_to_device"
    + ".compile_circuit_to_device",
    "clocks": {
        "q0.01": 6020000000.0,
        "q0.ro": 7040000000.0,
        "q1.01": 5020000000.0,
        "q1.ro": 6900000000.0,
    },
    "elements": {
        "q0": {
            "reset": {
                "factory_func": "quantify_scheduler.operations.pulse_library.IdlePulse",
                "factory_kwargs": {"duration": 0.0002},
            },
            "Rxy": {
                "factory_func": "quantify_scheduler.operations."
                + "pulse_factories.rxy_drag_pulse",
                "gate_info_factory_kwargs": ["theta", "phi"],
                "factory_kwargs": {
                    "amp180": 0.32,
                    "motzoi": 0.45,
                    "port": "q0:mw",
                    "clock": "q0.01",
                    "duration": 2e-08,
                },
            },
            "Z": {
                "factory_func": "quantify_scheduler.operations."
                + "pulse_library.SoftSquarePulse",
                "factory_kwargs": {
                    "amp": 0.23,
                    "duration": 4e-09,
                    "port": "q0:fl",
                    "clock": "cl0.baseband",
                },
            },
            "measure": {
                "factory_func": "quantify_scheduler.operations."
                + "measurement_factories.dispersive_measurement",
                "gate_info_factory_kwargs": ["acq_index", "bin_mode"],
                "factory_kwargs": {
                    "port": "q0:res",
                    "clock": "q0.ro",
                    "pulse_type": "SquarePulse",
                    "pulse_amp": 0.25,
                    "pulse_duration": 1.6e-07,
                    "acq_delay": 1.2e-07,
                    "acq_duration": 3e-07,
                    "acq_protocol": "SSBIntegrationComplex",
                    "acq_channel": 0,
                },
            },
        },
        "q1": {
            "reset": {
                "factory_func": "quantify_scheduler.operations.pulse_library.IdlePulse",
                "factory_kwargs": {"duration": 0.0002},
            },
            "Rxy": {
                "factory_func": "quantify_scheduler.operations."
                + "pulse_factories.rxy_drag_pulse",
                "gate_info_factory_kwargs": ["theta", "phi"],
                "factory_kwargs": {
                    "amp180": 0.4,
                    "motzoi": 0.25,
                    "port": "q1:mw",
                    "clock": "q1.01",
                    "duration": 2e-08,
                },
            },
            "measure": {
                "factory_func": "quantify_scheduler.operations."
                + "measurement_factories.dispersive_measurement",
                "gate_info_factory_kwargs": ["acq_index", "bin_mode"],
                "factory_kwargs": {
                    "port": "q1:res",
                    "clock": "q1.ro",
                    "pulse_type": "SquarePulse",
                    "pulse_amp": 0.21,
                    "pulse_duration": 1.6e-07,
                    "acq_delay": 1.2e-07,
                    "acq_duration": 3e-07,
                    "acq_protocol": "SSBIntegrationComplex",
                    "acq_channel": 1,
                },
            },
        },
    },
    "edges": {
        "q0-q1": {
            "CZ": {
                "factory_func": "quantify_scheduler.operations."
                + "pulse_library.SuddenNetZeroPulse",
                "factory_kwargs": {
                    "port": "q0:fl",
                    "clock": "cl0.baseband",
                    "amp_A": 0.5,
                    "amp_B": 0.4,
                    "net_zero_A_scale": 0.95,
                    "t_pulse": 2e-08,
                    "t_phi": 2e-09,
                    "t_integral_correction": 1e-08,
                },
            }
        }
    },
}
Edited by Damien Crielaard

Merge request reports

Loading