Skip to content

Commit

Permalink
Merge branch 'main' into kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacfomg committed Jan 19, 2024
2 parents 2e5eca6 + 1723585 commit 3416a8e
Show file tree
Hide file tree
Showing 26 changed files with 479 additions and 642 deletions.
27 changes: 27 additions & 0 deletions doc/source/tutorials/circuits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,30 @@ Returns the following plot:
.. note::
Executing circuits using the Qibolab backend results to automatic application of the transpilation and compilation pipelines (:ref:`main_doc_transpiler`) which convert the circuit to a pulse sequence that is executed by the given platform.
It is possible to modify these pipelines following the instructions in the :ref:`tutorials_transpiler` example.

QASM Execution
--------------

Qibolab also supports the execution of circuits starting from a QASM string. The QASM circuit:

.. testcode::

circuit = """// Generated by QIBO 0.2.4
OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
creg a[2];
cx q[0],q[2];
x q[1];
swap q[0],q[1];
cx q[1],q[0];
measure q[0] -> a[0];
measure q[2] -> a[1];"""

can be executed by passing it together with the platform name to the :func:`qibolab.execute_qasm` function:

.. testcode::

from qibolab import execute_qasm

result = execute_qasm(circuit, platform="dummy")
60 changes: 1 addition & 59 deletions examples/pulses_tutorial.ipynb

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions src/qibolab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
from pathlib import Path

from qibo import Circuit
from qibo.config import raise_error

from qibolab.execution_parameters import (
Expand Down Expand Up @@ -54,3 +55,25 @@ def create_platform(name, runcard=None):
if runcard is None:
return module.create()
return module.create(runcard)


def execute_qasm(circuit: str, platform, runcard=None, initial_state=None, nshots=1000):
"""Executes a QASM circuit.
Args:
circuit (str): the QASM circuit.
platform (str): the platform where to execute the circuit.
runcard (pathlib.Path): the path to the runcard used for the platform.
initial_state (:class:`qibo.models.circuit.Circuit`): Circuit to prepare the initial state.
If ``None`` the default ``|00...0>`` state is used.
nshots (int): Number of shots to sample from the experiment.
Returns:
``MeasurementOutcomes`` object containing the results acquired from the execution.
"""
from qibolab.backends import QibolabBackend

circuit = Circuit.from_qasm(circuit)
return QibolabBackend(platform, runcard).execute_circuit(
circuit, initial_state=initial_state, nshots=nshots
)
2 changes: 2 additions & 0 deletions src/qibolab/compilers/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from qibo.config import raise_error

from qibolab.compilers.default import (
cnot_rule,
cz_rule,
gpi2_rule,
identity_rule,
Expand Down Expand Up @@ -49,6 +50,7 @@ def default(cls):
gates.RZ: rz_rule,
gates.U3: u3_rule,
gates.CZ: cz_rule,
gates.CNOT: cnot_rule,
gates.GPI2: gpi2_rule,
gates.M: measurement_rule,
}
Expand Down
5 changes: 5 additions & 0 deletions src/qibolab/compilers/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ def cz_rule(gate, platform):
return platform.create_CZ_pulse_sequence(gate.qubits)


def cnot_rule(gate, platform):
"""CNOT applied as defined in the platform runcard."""
return platform.create_CNOT_pulse_sequence(gate.qubits)


def measurement_rule(gate, platform):
"""Measurement gate applied using the platform readout pulse."""
sequence = PulseSequence()
Expand Down
7 changes: 6 additions & 1 deletion src/qibolab/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ def remove_couplers(runcard):
return runcard


def load_dummy_runcard():
"""Loads the runcard YAML of the dummy platform."""
return load_runcard(pathlib.Path(__file__).parent / "dummy.yml")


def create_dummy(with_couplers: bool = True):
"""Create a dummy platform using the dummy instrument.
Expand All @@ -35,7 +40,7 @@ def create_dummy(with_couplers: bool = True):
twpa_pump.frequency = 1e9
twpa_pump.power = 10

runcard = load_runcard(pathlib.Path(__file__).parent / "dummy.yml")
runcard = load_dummy_runcard()
extras_folder = pathlib.Path(__file__).parent / "dummy"
if not with_couplers:
runcard = remove_couplers(runcard)
Expand Down
55 changes: 30 additions & 25 deletions src/qibolab/dummy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,105 +22,110 @@ native_gates:
relative_start: 0, phase: 0, type: qd}
RX12: {duration: 40, amplitude: 0.005, shape: Gaussian(5), frequency: 4700000000,
relative_start: 0, phase: 0, type: qd}
MZ: {duration: 2000, amplitude: 0.1, shape: Rectangular(), frequency: 5200000000.0,
MZ: {duration: 2000, amplitude: 0.1, shape: 'GaussianSquare(5, 0.75)', frequency: 5200000000.0,
relative_start: 0, phase: 0, type: ro}
1:
RX: {duration: 40, amplitude: 0.3, shape: 'Drag(5, -0.02)', frequency: 4200000000.0,
relative_start: 0, phase: 0, type: qd}
RX12: {duration: 40, amplitude: 0.0484, shape: 'Drag(5, -0.02)', frequency: 4855663000,
relative_start: 0, phase: 0, type: qd}
MZ: {duration: 2000, amplitude: 0.1, shape: Rectangular(), frequency: 4900000000.0,
MZ: {duration: 2000, amplitude: 0.1, shape: 'GaussianSquare(5, 0.75)', frequency: 4900000000.0,
relative_start: 0, phase: 0, type: ro}
2:
RX: {duration: 40, amplitude: 0.3, shape: 'Drag(5, -0.02)', frequency: 4500000000.0,
relative_start: 0, phase: 0, type: qd}
RX12: {duration: 40, amplitude: 0.005, shape: Gaussian(5), frequency: 2700000000,
relative_start: 0, phase: 0, type: qd}
MZ: {duration: 2000, amplitude: 0.1, shape: Rectangular(), frequency: 6100000000.0,
MZ: {duration: 2000, amplitude: 0.1, shape: 'GaussianSquare(5, 0.75)', frequency: 6100000000.0,
relative_start: 0, phase: 0, type: ro}
3:
RX: {duration: 40, amplitude: 0.3, shape: 'Drag(5, -0.02)', frequency: 4150000000.0,
relative_start: 0, phase: 0, type: qd}
RX12: {duration: 40, amplitude: 0.0484, shape: 'Drag(5, -0.02)', frequency: 5855663000,
relative_start: 0, phase: 0, type: qd}
MZ: {duration: 2000, amplitude: 0.1, shape: Rectangular(), frequency: 5800000000.0,
MZ: {duration: 2000, amplitude: 0.1, shape: 'GaussianSquare(5, 0.75)', frequency: 5800000000.0,
relative_start: 0, phase: 0, type: ro}
4:
RX: {duration: 40, amplitude: 0.3, shape: 'Drag(5, -0.02)', frequency: 4155663000,
relative_start: 0, phase: 0, type: qd}
RX12: {duration: 40, amplitude: 0.0484, shape: 'Drag(5, -0.02)', frequency: 5855663000,
relative_start: 0, phase: 0, type: qd}
MZ: {duration: 2000, amplitude: 0.1, shape: Rectangular(), frequency: 5500000000.0,
MZ: {duration: 2000, amplitude: 0.1, shape: 'GaussianSquare(5, 0.75)', frequency: 5500000000.0,
relative_start: 0, phase: 0, type: ro}
coupler:
0:
CP: {duration: 30, amplitude: 0.05, shape: Rectangular(), relative_start: 0, type: coupler, coupler: 0}
CP: {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', relative_start: 0, type: coupler, coupler: 0}
1:
CP: {duration: 30, amplitude: 0.05, shape: Rectangular(), relative_start: 0, type: coupler, coupler: 1}
CP: {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', relative_start: 0, type: coupler, coupler: 1}
3:
CP: {duration: 30, amplitude: 0.05, shape: Rectangular(), relative_start: 0, type: coupler, coupler: 3}
CP: {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', relative_start: 0, type: coupler, coupler: 3}
4:
CP: {duration: 30, amplitude: 0.05, shape: Rectangular(), relative_start: 0, type: coupler, coupler: 4}
CP: {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', relative_start: 0, type: coupler, coupler: 4}
two_qubit:
0-2:
CZ:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 0}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 0, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', coupler: 0, relative_start: 0,
type: coupler}
iSWAP:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 0, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', coupler: 0, relative_start: 0,
type: coupler}
1-2:
CZ:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 1, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', coupler: 1, relative_start: 0,
type: coupler}
iSWAP:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 1, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', coupler: 1, relative_start: 0,
type: coupler}
2-3:
CZ:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 3}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 3, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', coupler: 3, relative_start: 0,
type: coupler}
iSWAP:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 3, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', coupler: 3, relative_start: 0,
type: coupler}
CNOT:
- {duration: 40, amplitude: 0.3, shape: 'Drag(5, -0.02)', frequency: 4150000000.0,
relative_start: 0, phase: 0, type: qd, qubit: 2}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
2-4:
CZ:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 4}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 4, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', coupler: 4, relative_start: 0,
type: coupler}
iSWAP:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 4, relative_start: 0,
- {duration: 30, amplitude: 0.05, shape: 'GaussianSquare(5, 0.75)', coupler: 4, relative_start: 0,
type: coupler}

characterization:
Expand Down
27 changes: 7 additions & 20 deletions src/qibolab/instruments/qblox/cluster_qcm_bb.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,32 +740,19 @@ def play_sequence(self):
# Start used sequencers
self.device.start_sequencer(sequencer_number)

def start(self):
"""Empty method to comply with Instrument interface."""
pass

def stop(self):
"""Stops all sequencers."""

def disconnect(self):
"""Stops all sequencers, disconnect all the outputs from the AWG paths
of the sequencers."""
if not self.is_connected:
return
for sequencer_number in self._used_sequencers_numbers:
state = self.device.get_sequencer_state(sequencer_number)
if state.status != "STOPPED":
log.warning(
f"Device {self.device.sequencers[sequencer_number].name} did not stop normally\nstate: {state}"
)
try:
self.device.stop_sequencer()
except:
log.warning("Unable to stop sequencers")

try:
for port in self._ports:
self._ports[port].offset = 0

except:
log.warning("Unable to clear offsets")

def disconnect(self):
"""Empty method to comply with Instrument interface."""
self.device.stop_sequencer()
self.device.disconnect_outputs()
self.is_connected = False
self.device = None
23 changes: 9 additions & 14 deletions src/qibolab/instruments/qblox/cluster_qcm_rf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from qblox_instruments.qcodes_drivers.cluster import Cluster as QbloxCluster
from qblox_instruments.qcodes_drivers.qcm_qrm import QcmQrm as QbloxQrmQcm
from qibo.config import log

from qibolab.instruments.qblox.module import ClusterModule
from qibolab.instruments.qblox.q1asm import (
Expand Down Expand Up @@ -739,26 +740,20 @@ def play_sequence(self):
# Start used sequencers
self.device.start_sequencer(sequencer_number)

def start(self):
"""Empty method to comply with Instrument interface."""
pass

def stop(self):
"""Stops all sequencers."""
from qibo.config import log

def disconnect(self):
"""Stops all sequencers, disconnect all the outputs from the AWG paths
of the sequencers."""
if not self.is_connected:
return
for sequencer_number in self._used_sequencers_numbers:
state = self.device.get_sequencer_state(sequencer_number)
if state.status != "STOPPED":
log.warning(
f"Device {self.device.sequencers[sequencer_number].name} did not stop normally\nstate: {state}"
)
try:
self.device.stop_sequencer()
except:
log.warning("Unable to stop sequencers")

def disconnect(self):
"""Empty method to comply with Instrument interface."""
self.device.stop_sequencer()
self.device.disconnect_outputs()

self.is_connected = False
self.device = None
27 changes: 16 additions & 11 deletions src/qibolab/instruments/qblox/cluster_qrm_rf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1017,18 +1017,23 @@ def acquire(self):
# TODO: to be updated once the functionality of ExecutionResults is extended
return {key: acquisition.data for key, acquisition in acquisitions.items()}

def start(self):
"""Empty method to comply with Instrument interface."""
pass
def disconnect(self):
"""Stops all sequencers, disconnect all the outputs from the AWG paths
of the sequencers and disconnect all the inputs from the acquisition
paths of the sequencers."""

def stop(self):
"""Stops all sequencers."""
try:
self.device.stop_sequencer()
except:
raise RuntimeError(f"Error stopping sequencer for {self.device.name}")
if not self.is_connected:
return

for sequencer_number in self._used_sequencers_numbers:
state = self.device.get_sequencer_state(sequencer_number)
if state.status != "STOPPED":
log.warning(
f"Device {self.device.sequencers[sequencer_number].name} did not stop normally\nstate: {state}"
)
self.device.stop_sequencer()
self.device.disconnect_outputs()
self.device.disconnect_inputs()

def disconnect(self):
"""Empty method to comply with Instrument interface."""
self.is_connected = False
self.device = None
8 changes: 3 additions & 5 deletions src/qibolab/instruments/qblox/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ def connect(self):
# Connect modules
for module in self.modules.values():
module.connect(self.cluster)
module.start()
self.is_connected = True
log.info("QbloxController: all modules connected.")

Expand All @@ -69,7 +68,6 @@ def disconnect(self):
"""Disconnects all modules."""
if self.is_connected:
for module in self.modules.values():
module.stop()
module.disconnect()
self.cluster.close()
self.is_connected = False
Expand All @@ -85,11 +83,11 @@ def _termination_handler(self, signum, frame):
"""Calls all modules to stop if the program receives a termination
signal."""

log.warning("Termination signal received, stopping modules.")
log.warning("Termination signal received, disconnecting modules.")
if self.is_connected:
for name in self.modules:
self.modules[name].stop()
log.warning("QbloxController: all modules stopped.")
self.modules[name].disconnect()
log.warning("QbloxController: all modules are disconnected.")
exit(0)

def _set_module_channel_map(self, module: ClusterQRM_RF, qubits: dict):
Expand Down
Loading

0 comments on commit 3416a8e

Please sign in to comment.