Some checks failed
Build wheels / build (ubuntu-latest, 3.11) (push) Has been cancelled
Build wheels / build (ubuntu-latest, 3.12) (push) Has been cancelled
Build wheels / build (ubuntu-latest, 3.13) (push) Has been cancelled
docs / evaluate-label (push) Has been cancelled
Tests / check (push) Has been cancelled
docs / deploy-docs (push) Has been cancelled
Tests / build (ubuntu-latest, 3.11) (push) Has been cancelled
Tests / build (ubuntu-latest, 3.12) (push) Has been cancelled
Tests / build (ubuntu-latest, 3.13) (push) Has been cancelled
92 lines
2.7 KiB
Python
92 lines
2.7 KiB
Python
import math
|
|
|
|
import pytest
|
|
from qibo import Circuit, gates, hamiltonians
|
|
from qibo.symbols import X, Z
|
|
|
|
from qibotn.backends.qmatchatea import QMatchaTeaBackend
|
|
|
|
|
|
def build_observable(nqubits):
|
|
"""Helper function to construct a target observable."""
|
|
hamiltonian_form = 0
|
|
for i in range(nqubits):
|
|
hamiltonian_form += 0.5 * X(i % nqubits) * Z((i + 1) % nqubits)
|
|
|
|
hamiltonian = hamiltonians.SymbolicHamiltonian(form=hamiltonian_form)
|
|
return hamiltonian, hamiltonian_form
|
|
|
|
|
|
def build_GHZ(nqubits):
|
|
"""Helper function to construct a layered quantum circuit."""
|
|
circ = Circuit(nqubits)
|
|
circ.add(gates.H(0))
|
|
[circ.add(gates.CNOT(q, q + 1)) for q in range(nqubits - 1)]
|
|
return circ
|
|
|
|
|
|
def construct_targets(nqubits):
|
|
"""Construct strings of 1s and 0s of size `nqubits`."""
|
|
ones = "1" * nqubits
|
|
zeros = "0" * nqubits
|
|
return ones, zeros
|
|
|
|
|
|
@pytest.mark.parametrize("nqubits", [2, 10, 40])
|
|
def test_probabilities(backend, nqubits):
|
|
|
|
circ = build_GHZ(nqubits=nqubits)
|
|
|
|
if isinstance(backend, QMatchaTeaBackend):
|
|
# unbiased prob
|
|
out_u = backend.execute_circuit(
|
|
circuit=circ,
|
|
prob_type="U",
|
|
num_samples=1000,
|
|
).probabilities()
|
|
|
|
math.isclose(out_u[0], 0.5, abs_tol=1e-7)
|
|
math.isclose(out_u[1], 0.5, abs_tol=1e-7)
|
|
|
|
out_g = backend.execute_circuit(
|
|
circuit=circ,
|
|
prob_type="G",
|
|
prob_threshold=1.0,
|
|
).probabilities()
|
|
|
|
math.isclose(out_g[0], 0.5, abs_tol=1e-7)
|
|
math.isclose(out_g[1], 0.5, abs_tol=1e-7)
|
|
|
|
out_e = backend.execute_circuit(
|
|
circuit=circ,
|
|
prob_type="E",
|
|
prob_threshold=0.2,
|
|
).probabilities()
|
|
|
|
math.isclose(out_e[0], 0.5, abs_tol=1e-7)
|
|
math.isclose(out_e[1], 0.5, abs_tol=1e-7)
|
|
|
|
|
|
@pytest.mark.parametrize("nqubits", [2, 10, 40])
|
|
@pytest.mark.parametrize("nshots", [100, 1000])
|
|
def test_shots(backend, nqubits, nshots):
|
|
circ = build_GHZ(nqubits=nqubits)
|
|
ones, zeros = construct_targets(nqubits)
|
|
|
|
# For p = 0.5, sigma = sqrt(nshots * 0.5 * 0.5) = sqrt(nshots)/2.
|
|
sigma_threshold = 3 * (math.sqrt(nshots) / 2)
|
|
|
|
outcome = backend.execute_circuit(circ, nshots=nshots)
|
|
frequencies = outcome.frequencies()
|
|
|
|
shots_ones = frequencies.get(ones, 0)
|
|
shots_zeros = frequencies.get(zeros, 0)
|
|
|
|
# Check that the counts for both outcomes are within the 3-sigma threshold of nshots/2.
|
|
assert (
|
|
abs(shots_ones - (nshots / 2)) < sigma_threshold
|
|
), f"Count for {ones} deviates too much: {shots_ones} vs expected {nshots/2}"
|
|
assert (
|
|
abs(shots_zeros - (nshots / 2)) < sigma_threshold
|
|
), f"Count for {zeros} deviates too much: {shots_zeros} vs expected {nshots/2}"
|