Skip to content

Commit

Permalink
Merge pull request #1146 from qiboteam/entangling_capacity
Browse files Browse the repository at this point in the history
Add `seed` parameter to `quantum_info.entangling_capacity`
renatomello authored Jan 10, 2024
2 parents 0eeb6ae + 48bf93a commit ffc7c2b
Showing 2 changed files with 27 additions and 7 deletions.
20 changes: 18 additions & 2 deletions src/qibo/quantum_info/metrics.py
Original file line number Diff line number Diff line change
@@ -1049,7 +1049,7 @@ def meyer_wallach_entanglement(circuit, backend=None):
return entanglement


def entangling_capability(circuit, samples: int, backend=None):
def entangling_capability(circuit, samples: int, seed=None, backend=None):
"""Returns the entangling capability :math:`\\text{Ent}` of a parametrized
circuit, which is average Meyer-Wallach entanglement Q of the circuit, i.e.
@@ -1061,6 +1061,9 @@ def entangling_capability(circuit, samples: int, backend=None):
Args:
circuit (:class:`qibo.models.Circuit`): Parametrized circuit.
samples (int): number of samples to estimate the integral.
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. Default: ``None``.
backend (:class:`qibo.backends.abstract.Backend`, optional): backend to be used
in the execution. If ``None``, it uses :class:`qibo.backends.GlobalBackend`.
Defaults to ``None``.
@@ -1074,12 +1077,25 @@ def entangling_capability(circuit, samples: int, backend=None):
TypeError, f"samples must be type int, but it is type {type(samples)}."
)

if (
seed is not None
and not isinstance(seed, int)
and not isinstance(seed, np.random.Generator)
):
raise_error(
TypeError, "seed must be either type int or numpy.random.Generator."
)

if backend is None: # pragma: no cover
backend = GlobalBackend()

local_state = (
np.random.default_rng(seed) if seed is None or isinstance(seed, int) else seed
)

res = []
for _ in range(samples):
params = np.random.uniform(-np.pi, np.pi, circuit.trainable_gates.nparams)
params = local_state.uniform(-np.pi, np.pi, circuit.trainable_gates.nparams)
circuit.set_parameters(params)
entanglement = meyer_wallach_entanglement(circuit, backend=backend)
res.append(entanglement)
14 changes: 9 additions & 5 deletions tests/test_quantum_info_metrics.py
Original file line number Diff line number Diff line change
@@ -591,11 +591,15 @@ def test_meyer_wallach_entanglement(backend):
)


def test_entangling_capability(backend):
@pytest.mark.parametrize("seed", [None, 10, np.random.default_rng(10)])
def test_entangling_capability(backend, seed):
with pytest.raises(TypeError):
circuit = Circuit(1)
samples = 0.5
entangling_capability(circuit, samples, backend=backend)
entangling_capability(circuit, samples, seed=seed, backend=backend)
with pytest.raises(TypeError):
circuit = Circuit(1)
entangling_capability(circuit, samples=10, seed="10", backend=backend)

nqubits = 2
samples = 100
@@ -604,16 +608,16 @@ def test_entangling_capability(backend):
c1.add([gates.RX(q, 0, trainable=True) for q in range(nqubits)])
c1.add(gates.CNOT(0, 1))
c1.add([gates.RX(q, 0, trainable=True) for q in range(nqubits)])
ent_mw1 = entangling_capability(c1, samples, backend=backend)
ent_mw1 = entangling_capability(c1, samples, seed=seed, backend=backend)

c2 = Circuit(nqubits)
c2.add(gates.H(0))
c2.add(gates.CNOT(0, 1))
c2.add(gates.RX(0, 0, trainable=True))
ent_mw2 = entangling_capability(c2, samples, backend=backend)
ent_mw2 = entangling_capability(c2, samples, seed=seed, backend=backend)

c3 = Circuit(nqubits)
ent_mw3 = entangling_capability(c3, samples, backend=backend)
ent_mw3 = entangling_capability(c3, samples, seed=seed, backend=backend)

backend.assert_allclose(ent_mw3 < ent_mw1 < ent_mw2, True)

0 comments on commit ffc7c2b

Please sign in to comment.