diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 9c16c9d86..000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,12 +0,0 @@ - - - -Checklist: -- [ ] Reviewers confirm new code works as expected. -- [ ] Tests are passing. -- [ ] Coverage does not decrease. -- [ ] Documentation is updated. -- [ ] Compatibility with Qibo modules (Please edit this section if the current pull request is not compatible with the following branches). - - [ ] Qibo: `master` - - [ ] Qibolab: `main` - - [ ] Qibolab_platforms_qrc: `main` diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8ca92e8f0..ebfe30a14 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,11 +20,11 @@ repos: - id: isort args: ["--profile", "black"] - repo: https://github.com/asottile/pyupgrade - rev: v3.19.0 + rev: v3.19.1 hooks: - id: pyupgrade - repo: https://github.com/hadialqattan/pycln - rev: v2.4.0 + rev: v2.5.0 hooks: - id: pycln args: diff --git a/pyproject.toml b/pyproject.toml index 3165f2149..6cc1532cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "qibocal" -version = "0.1.1" +version = "0.1.2" description = "Qibo's quantum calibration, characterization and validation module." authors = ["The Qibo team"] license = "Apache License 2.0" diff --git a/src/qibocal/protocols/__init__.py b/src/qibocal/protocols/__init__.py index f6aa87e61..2d781b652 100644 --- a/src/qibocal/protocols/__init__.py +++ b/src/qibocal/protocols/__init__.py @@ -103,5 +103,6 @@ "standard_rb_2q", "standard_rb_2q_inter", "optimize_two_qubit_gate", + "mermin", "ramsey_zz", ] diff --git a/src/qibocal/protocols/readout_mitigation_matrix.py b/src/qibocal/protocols/readout_mitigation_matrix.py index 4272017f6..6c1c79262 100644 --- a/src/qibocal/protocols/readout_mitigation_matrix.py +++ b/src/qibocal/protocols/readout_mitigation_matrix.py @@ -7,7 +7,6 @@ from qibo import gates from qibo.backends import get_backend from qibo.models import Circuit -from qibolab import PulseSequence from scipy.sparse import lil_matrix from qibocal.auto.operation import Data, Parameters, QubitId, Results, Routine @@ -15,15 +14,11 @@ from qibocal.calibration import CalibrationPlatform from qibocal.config import log -from .utils import calculate_frequencies, computational_basis - @dataclass class ReadoutMitigationMatrixParameters(Parameters): """ReadoutMitigationMatrix matrix inputs.""" - pulses: Optional[bool] = True - """Get readout mitigation matrix using pulses. If False gates will be used.""" nshots: Optional[int] = None """Number of shots.""" relaxation_time: Optional[int] = None @@ -36,10 +31,14 @@ class ReadoutMitigationMatrixResults(Results): field(default_factory=dict) ) """Readout mitigation matrices (inverse of measurement matrix).""" - measurement_matrix: dict[tuple[QubitId, ...], npt.NDArray[np.float64]] = field( - default_factory=dict - ) - """Matrix containing measurement matrices for each state.""" + + +ReadoutMitigationMatrixType = np.dtype( + [ + ("state", int), + ("frequency", np.float64), + ] +) ReadoutMitigationMatrixId = tuple[Tuple[QubitId, ...], str, str] @@ -61,51 +60,6 @@ class ReadoutMitigationMatrixData(Data): data: dict[ReadoutMitigationMatrixId, float] = field(default_factory=dict) """Raw data acquited.""" - def add(self, qubits: list[QubitId], state: str, freqs: dict[str, int]): - """Adding frequency to data.""" - - for result_state, freq in freqs.items(): - self.data[ - qubits - + ( - state, - result_state, - ) - ] = freq - - for basis in [format(i, f"0{len(qubits)}b") for i in range(2 ** len(qubits))]: - if ( - qubits - + ( - state, - basis, - ) - not in self.data - ): - self.data[ - qubits - + ( - state, - basis, - ) - ] = 0 - - def matrix(self, qubits: list[QubitId]): - """Retrieve data for single qubits list.""" - - matrix = np.zeros((2 ** len(qubits), 2 ** len(qubits))) - for state in computational_basis(len(qubits)): - column = np.zeros(2 ** len(qubits)) - qubit_state_data = { - index: value - for index, value in self.data.items() - if index[-2] == state and qubits == list(index[: len(index) - 2]) - } - for index, value in qubit_state_data.items(): - column[(int(index[-1], 2))] = value / self.nshots - matrix[:, int(state, 2)] = np.flip(column) - return matrix - def _acquisition( params: ReadoutMitigationMatrixParameters, @@ -121,52 +75,54 @@ def _acquisition( for qubits in targets: nqubits = len(qubits) - for state in computational_basis(nqubits): - if params.pulses: - sequence = PulseSequence() - ro_pulses = {} - for q, bit in enumerate(state): - natives = platform.natives.single_qubit[qubits[q]] - if bit == "1": - sequence |= natives.RX() - sequence |= natives.MZ() - ro_pulses[qubits[q]] = list( - sequence.channel(platform.qubits[qubits[q]].acquisition) - )[-1] - results = platform.execute([sequence], nshots=params.nshots) - data.add( - tuple(qubits), state, calculate_frequencies(results, ro_pulses) - ) - else: - c = Circuit(len(qubits)) - for q, bit in enumerate(state): - if bit == "1": - c.add(gates.X(q)) - c.add(gates.M(*[i for i in range(len(state))])) - _, results = execute_transpiled_circuit( - c, qubits, backend, nshots=params.nshots, transpiler=transpiler + for i in range(2**nqubits): + state = format(i, f"0{nqubits}b") + c = Circuit( + nqubits, + ) + for q, bit in enumerate(state): + if bit == "1": + c.add(gates.X(q)) + c.add(gates.M(*range(nqubits))) + _, results = execute_transpiled_circuit( + c, qubits, backend, nshots=params.nshots, transpiler=transpiler + ) + frequencies = np.zeros(2 ** len(qubits)) + for i, freq in results.frequencies().items(): + frequencies[int(i, 2)] = freq + for freq in frequencies: + data.register_qubit( + ReadoutMitigationMatrixType, + (tuple(qubits)), + dict( + state=np.array([int(state, 2)]), + frequency=freq, + ), ) - data.add(tuple(qubits), state, dict(results.frequencies())) return data def _fit(data: ReadoutMitigationMatrixData) -> ReadoutMitigationMatrixResults: """Post processing for readout mitigation matrix protocol.""" readout_mitigation_matrix = {} - measurement_matrix = {} - for qubit in data.qubit_list: - matrix = data.matrix(qubit) - measurement_matrix[tuple(qubit)] = matrix.tolist() + for qubits in data.qubit_list: + qubit_data = data.data[tuple(qubits)] + mitigation_matrix = [] + for state in range(2 ** len(qubits)): + mitigation_matrix.append(qubit_data[qubit_data.state == state].frequency) + mitigation_matrix = np.vstack(mitigation_matrix) / data.nshots try: - readout_mitigation_matrix[tuple(qubit)] = np.linalg.inv(matrix).tolist() + readout_mitigation_matrix[tuple(qubits)] = np.linalg.inv( + mitigation_matrix + ).tolist() except np.linalg.LinAlgError as e: log.warning(f"ReadoutMitigationMatrix: the fitting was not succesful. {e}") - - return ReadoutMitigationMatrixResults( + res = ReadoutMitigationMatrixResults( readout_mitigation_matrix=readout_mitigation_matrix, - measurement_matrix=measurement_matrix, ) + return res + def _plot( data: ReadoutMitigationMatrixData, @@ -177,13 +133,15 @@ def _plot( fitting_report = "" figs = [] if fit is not None: - basis = computational_basis(len(target)) - z = fit.measurement_matrix[tuple(target)] - + computational_basis = [ + format(i, f"0{len(target)}b") for i in range(2 ** len(target)) + ] + measurement_matrix = np.linalg.inv(fit.readout_mitigation_matrix[tuple(target)]) + z = measurement_matrix fig = px.imshow( z, - x=basis, - y=basis[::-1], + x=computational_basis, + y=computational_basis, text_auto=True, labels={ "x": "Prepared States", diff --git a/src/qibocal/protocols/utils.py b/src/qibocal/protocols/utils.py index 6d7fe1543..264d8e638 100644 --- a/src/qibocal/protocols/utils.py +++ b/src/qibocal/protocols/utils.py @@ -44,6 +44,7 @@ """Confidence interval used to clean outliers.""" DELAY_FIT_PERCENTAGE = 10 """Percentage of the first and last points used to fit the cable delay.""" +STRING_TYPE = " str: diff --git a/tests/runcards/protocols.yml b/tests/runcards/protocols.yml index e0278280b..9c54bd387 100644 --- a/tests/runcards/protocols.yml +++ b/tests/runcards/protocols.yml @@ -777,19 +777,11 @@ actions: native: CZ parking: True - - id: readout_mitigation_matrix pulses + - id: readout_mitigation_matrix operation: readout_mitigation_matrix targets: [[0,1,2],[1,2]] parameters: nshots: 10 - pulses: True - - - id: readout_mitigation_matrix circuits - operation: readout_mitigation_matrix - targets: [[0,1,2],[1,2]] - parameters: - nshots: 10 - pulses: False - id: resonator_amplitude operation: resonator_amplitude