Skip to content

qiskit_pytest_helper.propagation

Helpers to test sample-based phase propagators on the Aer simulator.

Functions:

  • run_propagator –

    Simulate a sample-based propagator on the initial state psi.

  • exact_cycles –

    Return the normalized state after successful cycles of the protocol.

Attributes:

  • SIMULATOR_SEED –

    The seed of the simulated measurements, for reproducible tests.

SIMULATOR_SEED module-attribute

SIMULATOR_SEED = 1234

The seed of the simulated measurements, for reproducible tests.

run_propagator

run_propagator(propagator: QuantumCircuit, psi: Statevector) -> tuple[bool, NDArray[complex128]]

Simulate a sample-based propagator on the initial state psi.

The propagator acts on the registers psi and phi of n qubits each, with the n success flags as classical bits.

Returns:

  • bool –

    Whether all cycles succeeded, i.e. the flags are 0, and the final amplitudes

  • NDArray[complex128] –

    of the psi register, exact including their global phase, which requires the

  • tuple[bool, NDArray[complex128]] –

    phi register to be back in |0...0>.

Source code in packages-dev/qiskit-pytest-helper/src/qiskit_pytest_helper/propagation.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def run_propagator(
    propagator: QuantumCircuit, psi: Statevector
) -> tuple[bool, npt.NDArray[np.complex128]]:
    """Simulate a sample-based propagator on the initial state `psi`.

    The propagator acts on the registers `psi` and `phi` of `n` qubits each, with the
    `n` success flags as classical bits.

    Returns:
        Whether all cycles succeeded, i.e. the flags are 0, and the final amplitudes
        of the `psi` register, exact including their global phase, which requires the
        `phi` register to be back in `|0...0>`.
    """
    num_qubits = propagator.num_qubits // 2
    circuit = QuantumCircuit(*propagator.qregs, *propagator.cregs)
    circuit.initialize(psi, range(num_qubits))
    circuit.compose(propagator, circuit.qubits, circuit.clbits, inplace=True)
    circuit.save_statevector()  # type: ignore[attr-defined]

    simulator = aer_simulator(
        device="cpu", method="statevector", seed_simulator=SIMULATOR_SEED
    )
    result = simulator.run(transpile_exactly(circuit, simulator), shots=1).result()
    succeeded = result.get_counts().int_outcomes().get(0) == 1
    amplitudes = np.asarray(result.get_statevector().data)

    return succeeded, amplitudes[: 2**num_qubits]

exact_cycles

exact_cycles(psi: ArrayLike, phi: ArrayLike, deltas: ArrayLike) -> NDArray[complex128]

Return the normalized state after successful cycles of the protocol.

Each successful cycle maps the amplitudes psi_j to psi_j (1 + (e^(i delta) - 1) |phi_j|^2).

Source code in packages-dev/qiskit-pytest-helper/src/qiskit_pytest_helper/propagation.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def exact_cycles(
    psi: npt.ArrayLike, phi: npt.ArrayLike, deltas: npt.ArrayLike
) -> npt.NDArray[np.complex128]:
    """Return the normalized state after successful cycles of the protocol.

    Each successful cycle maps the amplitudes `psi_j` to
    `psi_j (1 + (e^(i delta) - 1) |phi_j|^2)`.
    """
    state: npt.NDArray[np.complex128] = np.asarray(psi, dtype=np.complex128)
    weights = np.abs(np.asarray(phi)) ** 2
    for delta in np.asarray(deltas, dtype=float):
        state = state * (1 + (np.exp(1j * delta) - 1) * weights)
        state = state / np.linalg.norm(state)
    return state