From e389d3c3f1e35b3dce8c5318d6a9c497c30509b0 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 2 Oct 2023 14:40:30 +0400 Subject: [PATCH 1/5] add `density_matrix` flag to `random_clifford` --- src/qibo/quantum_info/random_ensembles.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/qibo/quantum_info/random_ensembles.py b/src/qibo/quantum_info/random_ensembles.py index 8898f06f2c..f10d2d5ed2 100644 --- a/src/qibo/quantum_info/random_ensembles.py +++ b/src/qibo/quantum_info/random_ensembles.py @@ -557,6 +557,7 @@ def random_density_matrix( def random_clifford( nqubits: int, return_circuit: bool = True, + density_matrix: bool = False, seed=None, backend=None, ): @@ -567,6 +568,8 @@ def random_clifford( nqubits (int): number of qubits. return_circuit (bool, optional): if ``True``, returns a :class:`qibo.models.Circuit` object. If ``False``, returns an ``ndarray`` object. Defaults to ``False``. + density_matrix (bool, optional): used when ``return_circuit=True``. If `True`, + the circuit would evolve density matrices. Defaults to ``False``. seed (int or :class:`numpy.random.Generator`, optional): Either a generator of random numbers or a fixed seed to initialize a generator. If ``None``, initializes a generator with a random seed. Defaults to ``None``. @@ -686,6 +689,8 @@ def random_clifford( random_pauli(nqubits, depth=1, return_circuit=True, seed=seed, backend=backend), ) + clifford_circuit.density_matrix = density_matrix + if return_circuit is False: clifford_circuit = clifford_circuit.unitary(backend=backend) From 615d9c0861f8f9e83c045bd4cb9ed853c3959fbf Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 2 Oct 2023 14:45:25 +0400 Subject: [PATCH 2/5] update test --- tests/test_quantum_info_random.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/test_quantum_info_random.py b/tests/test_quantum_info_random.py index d0e3e3ad65..58922aff06 100644 --- a/tests/test_quantum_info_random.py +++ b/tests/test_quantum_info_random.py @@ -273,9 +273,10 @@ def test_random_density_matrix(backend, dims, pure, metric, basis, normalize): @pytest.mark.parametrize("seed", [10]) +@pytest.mark.parametrize("density_matrix", [False, True]) @pytest.mark.parametrize("return_circuit", [True, False]) @pytest.mark.parametrize("nqubits", [1, 2]) -def test_random_clifford(backend, nqubits, return_circuit, seed): +def test_random_clifford(backend, nqubits, return_circuit, density_matrix, seed): with pytest.raises(TypeError): test = random_clifford( nqubits="1", return_circuit=return_circuit, backend=backend @@ -301,7 +302,11 @@ def test_random_clifford(backend, nqubits, return_circuit, seed): result = backend.cast(result, dtype=result.dtype) matrix = random_clifford( - nqubits, return_circuit=return_circuit, seed=seed, backend=backend + nqubits, + return_circuit=return_circuit, + density_matrix=density_matrix, + seed=seed, + backend=backend, ) if return_circuit: From e171201f2783e4119722a97ac60d91962efbc455 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 2 Oct 2023 14:59:59 +0400 Subject: [PATCH 3/5] include `density_matric` in `random_pauli` --- src/qibo/quantum_info/random_ensembles.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/qibo/quantum_info/random_ensembles.py b/src/qibo/quantum_info/random_ensembles.py index f10d2d5ed2..682916db57 100644 --- a/src/qibo/quantum_info/random_ensembles.py +++ b/src/qibo/quantum_info/random_ensembles.py @@ -675,7 +675,9 @@ def random_clifford( delta_matrix[k, j] = b # get first element of the Borel group - clifford_circuit = _operator_from_hadamard_free_group(gamma_matrix, delta_matrix) + clifford_circuit = _operator_from_hadamard_free_group( + gamma_matrix, delta_matrix, density_matrix + ) # Apply permutated Hadamard layer for qubit, had in enumerate(hadamards): @@ -686,11 +688,10 @@ def random_clifford( clifford_circuit += _operator_from_hadamard_free_group( gamma_matrix_prime, delta_matrix_prime, + density_matrix, random_pauli(nqubits, depth=1, return_circuit=True, seed=seed, backend=backend), ) - clifford_circuit.density_matrix = density_matrix - if return_circuit is False: clifford_circuit = clifford_circuit.unitary(backend=backend) @@ -703,6 +704,7 @@ def random_pauli( max_qubits: Optional[int] = None, subset: Optional[list] = None, return_circuit: bool = True, + density_matrix: bool = False, seed=None, backend=None, ): @@ -725,6 +727,8 @@ def random_pauli( return_circuit (bool, optional): if ``True``, returns a :class:`qibo.models.Circuit` object. If ``False``, returns an ``ndarray`` with shape (qubits, depth, 2, 2) that contains all Pauli matrices that were sampled. Defaults to ``True``. + density_matrix (bool, optional): used when ``return_circuit=True``. If `True`, + the circuit would evolve density matrices. Defaults to ``False``. seed (int or :class:`numpy.random.Generator`, optional): Either a generator of random numbers or a fixed seed to initialize a generator. If ``None``, initializes a generator with a random seed. Defaults to ``None``. @@ -824,7 +828,7 @@ def random_pauli( indexes = [[keys[item] for item in row] for row in indexes] if return_circuit: - gate_grid = Circuit(max_qubits) + gate_grid = Circuit(max_qubits, density_matrix=density_matrix) for qubit, row in zip(qubits, indexes): for column_item in row: if subset[column_item] != gates.I: @@ -1105,7 +1109,9 @@ def _sample_from_quantum_mallows_distribution(nqubits: int, local_state): return hadamards, permutations -def _operator_from_hadamard_free_group(gamma_matrix, delta_matrix, pauli_operator=None): +def _operator_from_hadamard_free_group( + gamma_matrix, delta_matrix, density_matrix: bool = False, pauli_operator=None +): """Calculates an element :math:`F` of the Hadamard-free group :math:`\\mathcal{F}_{n}`, where :math:`n` is the number of qubits ``nqubits``. For more details, see Reference [1]. @@ -1113,6 +1119,8 @@ def _operator_from_hadamard_free_group(gamma_matrix, delta_matrix, pauli_operato Args: gamma_matrix (ndarray): :math:`\\, n \\times n \\,` binary matrix. delta_matrix (ndarray): :math:`\\, n \\times n \\,` binary matrix. + density_matrix (bool, optional): used when ``return_circuit=True``. If `True`, + the circuit would evolve density matrices. Defaults to ``False``. pauli_operator (:class:`qibo.models.Circuit`, optional): a :math:`n`-qubit Pauli operator. If ``None``, it is assumed to be the Identity. Defaults to ``None``. @@ -1133,7 +1141,7 @@ def _operator_from_hadamard_free_group(gamma_matrix, delta_matrix, pauli_operato ) nqubits = len(gamma_matrix) - circuit = Circuit(nqubits) + circuit = Circuit(nqubits, density_matrix=density_matrix) if pauli_operator is not None: circuit += pauli_operator From ac86738d64b341031b2108314ad04a20b0bf6c76 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 2 Oct 2023 15:01:06 +0400 Subject: [PATCH 4/5] update tests --- tests/test_quantum_info_random.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/test_quantum_info_random.py b/tests/test_quantum_info_random.py index 58922aff06..378cb0e5ad 100644 --- a/tests/test_quantum_info_random.py +++ b/tests/test_quantum_info_random.py @@ -379,8 +379,11 @@ def test_pauli_single(backend): @pytest.mark.parametrize("max_qubits", [None]) @pytest.mark.parametrize("subset", [None, ["I", "X"]]) @pytest.mark.parametrize("return_circuit", [True, False]) +@pytest.mark.parametrize("density_matrix", [False, True]) @pytest.mark.parametrize("seed", [10]) -def test_random_pauli(backend, qubits, depth, max_qubits, subset, return_circuit, seed): +def test_random_pauli( + backend, qubits, depth, max_qubits, subset, return_circuit, density_matrix, seed +): result_complete_set = np.array( [ [0.0 + 0.0j, 1.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], @@ -395,7 +398,7 @@ def test_random_pauli(backend, qubits, depth, max_qubits, subset, return_circuit result_subset = backend.identity_density_matrix(2, normalize=False) matrix = random_pauli( - qubits, depth, max_qubits, subset, return_circuit, seed, backend + qubits, depth, max_qubits, subset, return_circuit, density_matrix, seed, backend ) if return_circuit: From 777549a2d48a66c8f974f55cc12f1a97db8d2fe7 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 2 Oct 2023 15:18:49 +0400 Subject: [PATCH 5/5] fix test --- src/qibo/quantum_info/random_ensembles.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/random_ensembles.py b/src/qibo/quantum_info/random_ensembles.py index 682916db57..e13c981577 100644 --- a/src/qibo/quantum_info/random_ensembles.py +++ b/src/qibo/quantum_info/random_ensembles.py @@ -689,7 +689,14 @@ def random_clifford( gamma_matrix_prime, delta_matrix_prime, density_matrix, - random_pauli(nqubits, depth=1, return_circuit=True, seed=seed, backend=backend), + random_pauli( + nqubits, + depth=1, + return_circuit=True, + density_matrix=density_matrix, + seed=seed, + backend=backend, + ), ) if return_circuit is False: