Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interleaved RB #864

Merged
merged 32 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a3e045e
feat: 1st draft for the interleaved
Jacfomg May 21, 2024
b8ccf6b
fix: tests
Jacfomg May 21, 2024
67573ab
fix: tests
Jacfomg May 21, 2024
64ca47b
Merge branch '2q_RB' into 2q_rb_interleaved
Jacfomg May 22, 2024
a87f7b5
fix: forgot function
Jacfomg May 22, 2024
67b9dc7
wip: proper interleave
Jacfomg May 22, 2024
301df90
Merge branch '2q_RB' into 2q_rb_interleaved
Jacfomg May 22, 2024
2d037af
feat: Add interleave parameter
Jacfomg May 22, 2024
d0b8a47
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 22, 2024
a636f88
fix: remove unused
Jacfomg May 22, 2024
31642bf
Merge branch '2q_rb_interleaved' of https://github.com/qiboteam/qiboc…
Jacfomg May 22, 2024
d363455
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 22, 2024
d6ba16f
fix: tmp_path on tests
Jacfomg May 23, 2024
2de76b3
Merge branch '2q_rb_interleaved' of https://github.com/qiboteam/qiboc…
Jacfomg May 23, 2024
933b51e
Merge branch 'main' into 2q_rb_interleaved
Jacfomg Jul 23, 2024
3c233f4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2024
4224415
fix: platform patch
Jacfomg Jul 23, 2024
5ba40d9
Merge branch '2q_rb_interleaved' of https://github.com/qiboteam/qiboc…
Jacfomg Jul 23, 2024
29cc3dc
fix: argument order
Jacfomg Jul 23, 2024
9c7d1b1
feat: fix tests and interleaved gate for CZ
Jacfomg Jul 23, 2024
2a79e37
Update src/qibocal/protocols/randomized_benchmarking/standard_rb_2q_i…
Jacfomg Jul 26, 2024
8846702
Update src/qibocal/protocols/randomized_benchmarking/standard_rb_2q_i…
Jacfomg Jul 26, 2024
30468ee
fix: docs
Jacfomg Jul 26, 2024
962c951
Merge branch '2q_rb_interleaved' of https://github.com/qiboteam/qiboc…
Jacfomg Jul 26, 2024
c3af513
Merge branch 'main' into 2q_rb_interleaved
Jacfomg Jul 29, 2024
b7af56e
fix: conflicts
Jacfomg Jul 29, 2024
79bd4dd
fix: comments
Jacfomg Aug 7, 2024
fd141d8
fix: remove comment
Jacfomg Aug 7, 2024
a0c207d
Merge branch 'main' into 2q_rb_interleaved
Jacfomg Aug 7, 2024
0aa6469
fix: Minor fixes
andrea-pasquale Aug 14, 2024
c03b4a9
Merge branch 'main' into 2q_rb_interleaved
andrea-pasquale Aug 14, 2024
667e954
fix: Fix dummy tests
andrea-pasquale Aug 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/qibocal/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
from .randomized_benchmarking.filtered_rb import filtered_rb
from .randomized_benchmarking.standard_rb import standard_rb
from .randomized_benchmarking.standard_rb_2q import standard_rb_2q
from .randomized_benchmarking.standard_rb_2q_inter import standard_rb_2q_inter
from .readout_characterization import readout_characterization
from .readout_mitigation_matrix import readout_mitigation_matrix
from .readout_optimization.resonator_amplitude import resonator_amplitude
Expand Down Expand Up @@ -144,4 +145,5 @@
"rabi_length_frequency",
"rabi_length_frequency_signal",
"standard_rb_2q",
"standard_rb_2q_inter",
]
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def _acquisition(
RBData: The depths, samples and ground state probability of each experiment in the scan.
"""

return rb_acquisition(params, targets, add_inverse_layer=False)
return rb_acquisition(params, platform, targets, add_inverse_layer=False)


def _fit(data: RBData) -> FilteredRBResult:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def _acquisition(
RBData: The depths, samples and ground state probability of each experiment in the scan.
"""

return rb_acquisition(params, targets)
return rb_acquisition(params, platform, targets)


def _fit(data: RBData) -> StandardRBResult:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def _acquisition(
) -> RB2QData:
"""Data acquisition for two qubit Standard Randomized Benchmarking."""

return twoq_rb_acquisition(params, targets)
return twoq_rb_acquisition(params, platform, targets)


def _fit(data: RB2QData) -> StandardRBResult:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from dataclasses import dataclass

import numpy as np
from qibolab.platform import Platform
from qibolab.qubits import QubitPairId

from qibocal.auto.operation import Routine
from qibocal.protocols.randomized_benchmarking.standard_rb import _plot
from qibocal.protocols.randomized_benchmarking.standard_rb_2q import (
StandardRB2QParameters,
)

from .utils import RB2QInterData, StandardRBResult, fit, twoq_rb_acquisition


@dataclass
class StandardRB2QInterParameters(StandardRB2QParameters):
"""Parameters for the standard 2q randomized benchmarking protocol."""

interleave: str = "CZ"
"""Gate to interleave"""


@dataclass
class StandardRB2QInterResult(StandardRBResult):
"""Standard RB outputs."""

fidelity_cz: dict[QubitPairId, list] = None
"""The overall fidelity for the CZ gate and its uncertainty."""


def _acquisition(
params: StandardRB2QInterParameters,
platform: Platform,
targets: list[QubitPairId],
) -> RB2QInterData:
"""Data acquisition for two qubit Interleaved Randomized Benchmarking."""

data = twoq_rb_acquisition(params, platform, targets, interleave=params.interleave)

fidelity = {}
for target in targets:
fidelity[target] = platform.pairs[target].gate_fidelity
data.fidelity = fidelity

return data


def _fit(data: RB2QInterData) -> StandardRB2QInterResult:
"""Takes a data frame, extracts the depths and the signal and fits it with an
exponential function y = Ap^x+B.

Args:
data: Data from the data acquisition stage.

Returns:
StandardRB2QInterResult: Aggregated and processed data.
"""

qubits = data.pairs
results = fit(qubits, data)

# FIXME: I can only get the data.fidelity if there is an acquisition step
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which cases you don't have an acquisition step?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when you just want to plot becuase you ran a new 2qRB but not interleaved for example

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the problem here. Either you run a 2qRb or a 2qInterleavedR, no?

if data.fidelity is not None:
fidelity_cz = {}
for qubit in qubits:
fid_cz = results.fidelity[qubit] / data.fidelity[qubit][0]
uncertainty_cz = np.sqrt(
1
/ data.fidelity[qubit][0] ** 2
* results.fit_uncertainties[qubit][1] ** 2
+ (results.fidelity[qubit] / data.fidelity[qubit][0] ** 2) ** 2
* data.fidelity[qubit][1] ** 2
)
fidelity_cz[qubit] = [fid_cz, uncertainty_cz]

new_results = StandardRB2QInterResult(
results.fidelity,
results.pulse_fidelity,
results.fit_parameters,
results.fit_uncertainties,
results.error_bars,
fidelity_cz,
)
else:
new_results = StandardRB2QInterResult(
results.fidelity,
results.pulse_fidelity,
results.fit_parameters,
results.fit_uncertainties,
results.error_bars,
)

return new_results


standard_rb_2q_inter = Routine(_acquisition, _fit, _plot)
41 changes: 34 additions & 7 deletions src/qibocal/protocols/randomized_benchmarking/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from qibo.backends import GlobalBackend
from qibo.config import raise_error
from qibo.models import Circuit
from qibolab.platform import Platform
from qibolab.qubits import QubitId, QubitPairId

from qibocal.auto.operation import Data, Parameters, Results
Expand Down Expand Up @@ -121,14 +122,15 @@ def random_circuits(
inverse_layer=True,
single_qubit=True,
file_inv=pathlib.Path(),
interleave=None,
) -> Iterable:
"""Returns random (self-inverting) Clifford circuits."""

circuits = []
indexes = defaultdict(list)
for _ in range(niter):
for target in targets:
circuit, random_index = layer_circuit(rb_gen, depth, target)
circuit, random_index = layer_circuit(rb_gen, depth, target, interleave)
if inverse_layer:
add_inverse_layer(circuit, rb_gen, single_qubit, file_inv)
add_measurement_layer(circuit)
Expand Down Expand Up @@ -306,6 +308,14 @@ def extract_probabilities(self, qubits):
return probs


@dataclass
class RB2QInterData(RB2QData):
"""The output of the acquisition function."""

fidelity: dict[QubitPairId, list] = None
"""The interleaved fidelity of this qubit."""


@dataclass
class StandardRBResult(Results):
"""Standard RB outputs."""
Expand All @@ -324,20 +334,24 @@ class StandardRBResult(Results):

def setup(
params: Parameters,
platform: Platform,
single_qubit: bool = True,
interleave: Optional[str] = None,
):
"""
Set up the randomized benchmarking experiment backend, noise model and data class.

Args:
params (Parameters): The parameters for the experiment.
single_qubit (bool, optional): Flag indicating whether the experiment is for a single qubit or two qubits. Defaults to True.
interleave: (str, optional): The type of interleaving to apply. Defaults to None.

Returns:
tuple: A tuple containing the experiment data, noise model, and backend.
"""

backend = GlobalBackend()
backend.platform = platform
# For simulations, a noise model can be added.
noise_model = None
if params.noise_model is not None:
Expand All @@ -351,6 +365,8 @@ def setup(
params.noise_params = noise_model.params.tolist()
# Set up the scan (here an iterator of circuits of random clifford gates with an inverse).
cls = RBData if single_qubit else RB2QData
if isinstance(cls, RB2QData) and interleave is not None:
cls = RB2QInterData
Jacfomg marked this conversation as resolved.
Show resolved Hide resolved
data = cls(
depths=params.depths,
uncertainties=params.uncertainties,
Expand Down Expand Up @@ -404,6 +420,7 @@ def get_circuits(
add_inverse_layer,
single_qubit,
inv_file,
interleave,
)

circuits.extend(circuits_depth)
Expand Down Expand Up @@ -463,6 +480,7 @@ def execute_circuits(circuits, targets, params, backend, single_qubit=True):

def rb_acquisition(
params: Parameters,
platform: Platform,
targets: list[QubitId],
add_inverse_layer: bool = True,
interleave: str = None,
Expand All @@ -480,7 +498,7 @@ def rb_acquisition(
Returns:
RBData: The depths, samples, and ground state probability of each experiment in the scan.
"""
data, noise_model, backend = setup(params, single_qubit=True)
data, noise_model, backend = setup(params, platform, single_qubit=True)
circuits, indexes, npulses_per_clifford = get_circuits(
params, targets, add_inverse_layer, interleave, noise_model, single_qubit=True
)
Expand Down Expand Up @@ -509,10 +527,11 @@ def rb_acquisition(

def twoq_rb_acquisition(
params: Parameters,
platform: Platform,
targets: list[QubitPairId],
add_inverse_layer: bool = True,
interleave: str = None,
) -> RB2QData:
) -> Union[RB2QData, RB2QInterData]:
"""
The data acquisition stage of two qubit Standard Randomized Benchmarking.

Expand All @@ -526,7 +545,7 @@ def twoq_rb_acquisition(
RB2QData: The acquired data for two qubit randomized benchmarking.
"""

data, noise_model, backend = setup(params, single_qubit=False)
data, noise_model, backend = setup(params, platform, single_qubit=False)
circuits, indexes, npulses_per_clifford = get_circuits(
params, targets, add_inverse_layer, interleave, noise_model, single_qubit=False
)
Expand Down Expand Up @@ -559,13 +578,16 @@ def twoq_rb_acquisition(
return data


def layer_circuit(rb_gen: Callable, depth: int, target) -> tuple[Circuit, dict]:
def layer_circuit(
rb_gen: Callable, depth: int, target, interleave: str = None
) -> tuple[Circuit, dict]:
"""Creates a circuit of `depth` layers from a generator `layer_gen` yielding `Circuit` or `Gate`
and a dictionary with random indexes used to select the clifford gates.

Args:
layer_gen (Callable): Should return gates or a full circuit specifying a layer.
depth (int): Number of layers.
interleave (str, optional): Interleaving pattern for the circuits. Defaults to None.

Returns:
Circuit: with `depth` many layers.
Expand All @@ -582,14 +604,19 @@ def layer_circuit(rb_gen: Callable, depth: int, target) -> tuple[Circuit, dict]:
for _ in range(depth):
# Generate a layer.
new_layer, random_index = rb_gen_layer
random_indexes.append(random_index)
new_circuit = Circuit(nqubits)
if nqubits == 1:
new_circuit.add(new_layer)
elif nqubits == 2:
for gate in new_layer:
new_circuit.add(gate)

random_indexes.append(random_index)
# FIXME: General interleave
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raise a not supported error instead of a FIXME

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

if interleave == "CZ":
interleaved_clifford = rb_gen.two_qubit_cliffords["13"]
interleaved_clifford_gate = clifford2gates(interleaved_clifford)
new_circuit.add(interleaved_clifford_gate)
random_indexes.append("13")
Comment on lines +621 to +624
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just create the CZ with Qibo ? Since the 2qRB files are merely one possibility, let's make every effort to separate the Qibocal library from them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, here it should be better to create the CZ with Qibo


if full_circuit is None: # instantiate in first loop
full_circuit = Circuit(new_circuit.nqubits)
Expand Down
8 changes: 8 additions & 0 deletions tests/runcards/protocols.yml
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,14 @@ actions:
niter: 5
nshots: 50

- id: standard rb 2q interleaved
operation: standard_rb_2q_inter
targets: [[0,2]]
parameters:
depths: [1, 2, 3, 5]
niter: 5
nshots: 50

- id: chevron id
operation: chevron
targets: [[0, 2],[1,2]]
Expand Down