示例#1
0
    def __init__(self, backend: BaseBackend, optimisation_level: int = 1):
        """Identifies a Qiskit backend and provides the corresponding default
        compilation pass from pytket as a
        :py:class:`qiskit.transpiler.TransformationPass`.

        :param backend: The Qiskit backend to target. Accepts Aer or IBMQ backends.
        :type backend: BaseBackend
        :param optimisation_level: The level of optimisation to perform during
            compilation. Level 0 just solves the device constraints without
            optimising. Level 1 additionally performs some light optimisations.
            Level 2 adds more intensive optimisations that can increase compilation
            time for large circuits. Defaults to 1.
        :type optimisation_level: int, optional
        """
        if not isinstance(backend, BaseBackend):
            raise ValueError("Requires BaseBackend instance")
        if isinstance(backend._provider, AerProvider):
            tk_backend = self._aer_backend_map[type(backend).__name__]()
        elif isinstance(backend._provider, AccountProvider):
            tk_backend = IBMQBackend(backend.name())
        else:
            raise NotImplementedError(
                "This backend provider is not supported.")
        super().__init__(
            tk_backend.default_compilation_pass(optimisation_level))
def test_compile_x() -> None:
    # TKET-1028
    b = IBMQBackend("ibmq_santiago", hub="ibm-q", group="open", project="main")
    c = Circuit(1).X(0)
    for ol in range(3):
        c1 = c.copy()
        b.compile_circuit(c1, optimisation_level=ol)
        assert c1.n_gates == 1
def test_default_pass() -> None:
    b = IBMQBackend("ibmq_santiago", hub="ibm-q", group="open", project="main")
    for ol in range(3):
        comp_pass = b.default_compilation_pass(ol)
        c = Circuit(3, 3)
        c.H(0)
        c.CX(0, 1)
        c.CSWAP(1, 0, 2)
        c.ZZPhase(0.84, 2, 0)
        c.measure_all()
        comp_pass.apply(c)
        for pred in b.required_predicates:
            assert pred.verify(c)
def test_remote_simulator() -> None:
    remote_qasm = IBMQBackend("ibmq_qasm_simulator",
                              hub="ibm-q",
                              group="open",
                              project="main")
    c = Circuit(3).CX(0, 1)
    c.add_gate(OpType.ZZPhase, 0.1, [0, 1])
    c.add_gate(OpType.CY, [0, 1])
    c.add_gate(OpType.CCX, [0, 1, 2])
    c.measure_all()

    assert remote_qasm.valid_circuit(c)

    assert sum(remote_qasm.get_counts(c, 10).values()) == 10
def test_cancellation_ibmq() -> None:
    b = IBMQBackend("ibmq_santiago", hub="ibm-q", group="open", project="main")
    c = circuit_gen(True)
    b.compile_circuit(c)
    h = b.process_circuit(c, 10)
    b.cancel(h)
    print(b.circuit_status(h))
def test_device() -> None:
    c = circuit_gen(False)
    b = IBMQBackend("ibmq_santiago", hub="ibm-q", group="open", project="main")
    assert b._max_per_job == 75
    operator = QubitPauliOperator({
        QubitPauliString(Qubit(0), Pauli.Z): 1.0,
        QubitPauliString(Qubit(0), Pauli.X): 0.5,
    })
    val = get_operator_expectation_value(c, operator, b, 8000)
    print(val)
    c1 = circuit_gen(True)
    c2 = circuit_gen(True)
    b.compile_circuit(c1)
    b.compile_circuit(c2)

    print(b.get_shots(c1, n_shots=10))
    print(b.get_shots(c2, n_shots=10))
def test_compilation_correctness() -> None:
    c = Circuit(5)
    c.H(0).H(1).H(2)
    c.CX(0, 1).CX(1, 2)
    c.Rx(0.25, 1).Ry(0.75, 1).Rz(0.5, 2)
    c.CCX(2, 1, 0)
    c.CY(1, 0).CY(2, 1)
    c.H(0).H(1).H(2)
    c.Rz(0.125, 0)
    c.X(1)
    c.Rz(0.125, 2).X(2).Rz(0.25, 2)
    c.SX(3).Rz(0.125, 3).SX(3)
    c.CX(0, 3).CX(0, 4)
    u_backend = AerUnitaryBackend()
    u = u_backend.get_unitary(c)
    ibm_backend = IBMQBackend("ibmq_santiago",
                              hub="ibm-q",
                              group="open",
                              project="main")
    for ol in range(3):
        p = ibm_backend.default_compilation_pass(optimisation_level=ol)
        cu = CompilationUnit(c)
        p.apply(cu)
        c1 = cu.circuit
        compiled_u = u_backend.get_unitary(c1)

        # Adjust for placement
        imap = cu.initial_map
        fmap = cu.final_map
        c_idx = {c.qubits[i]: i for i in range(5)}
        c1_idx = {c1.qubits[i]: i for i in range(5)}
        ini = {c_idx[qb]: c1_idx[node] for qb, node in imap.items()}
        inv_fin = {c1_idx[node]: c_idx[qb] for qb, node in fmap.items()}
        m_ini = lift_perm(ini)
        m_inv_fin = lift_perm(inv_fin)

        assert compare_unitaries(u, m_inv_fin @ compiled_u @ m_ini)
示例#8
0
def get_backend(provider, qpu):
    """
    Get the backend instance by name
    :param provider:
    :param qpu:
    :return:
    """

    if provider.lower() == "ibmq":
        try:
            return IBMQBackend(qpu)
        except NoIBMQAccountError:
            return None

    if provider.lower() == "rigetti":
        # Create a connection to the forest SDK
        connection = ForestConnection(
            sync_endpoint=f"http://{qvm_hostname}:{qvm_port}",
            compiler_endpoint=f"tcp://{quilc_hostname}:{quilc_port}")

        return ForestBackend(qpu, simulator=True, connection=connection)

    # Default if no provider matched
    return None
def test_machine_debug() -> None:
    backend = IBMQBackend("ibmq_santiago",
                          hub="ibm-q",
                          group="open",
                          project="main")
    backend._MACHINE_DEBUG = True
    c = Circuit(2, 2).H(0).CX(0, 1).measure_all()
    with pytest.raises(CircuitNotValidError) as errorinfo:
        handles = backend.process_circuits([c, c.copy()], n_shots=2)
    assert "in submitted does not satisfy GateSetPredicate" in str(
        errorinfo.value)
    backend.compile_circuit(c)
    handles = backend.process_circuits([c, c.copy()], n_shots=4)
    from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX

    assert all(
        cast(str, hand[0]).startswith(_DEBUG_HANDLE_PREFIX)
        for hand in handles)

    correct_shots = np.zeros((4, 2))
    correct_counts = {(0, 0): 4}

    shots = backend.get_shots(c, n_shots=4)
    assert np.all(shots == correct_shots)
    counts = backend.get_counts(c, n_shots=4)
    assert counts == correct_counts

    newshots = backend.get_shots(c, 4)
    assert np.all(newshots == correct_shots)
    newcounts = backend.get_counts(c, 4)
    assert newcounts == correct_counts
示例#10
0
    elif backend.supports_shots:
        syn_res_index = state_circuit.bit_readout[syn_res]
        pauli_circuits, coeffs, energy = gen_pauli_measurement_circuits(
            state_circuit, compiler_pass(backend), operator)
        handles = backend.process_circuits(pauli_circuits, n_shots=n_shots)
        for handle, coeff in zip(handles, coeffs):
            res = backend.get_result(handle)
            filtered = filter_shots(res, syn_res)
            energy += coeff * expectation_from_shots(filtered)
            backend.pop_result(handle)
        return energy
    else:
        raise NotImplementedError(
            "Implementation for state and counts to be written")


# ...and then run it for our ansatz. `AerBackend` supports faster expectation value from snapshopts (using the `AerBackend.get_operator_expectation_value` method), but this only works when all the qubits in the circuit are default register qubits that go up from 0. So we will need to rename `synq`.

from pytket.extensions.qiskit import IBMQBackend, AerBackend

ansatz.rename_units({Qubit("synq", 0): Qubit("q", 4)})

print(expectation_value(ansatz, hamiltonian, AerBackend(), 8000))
print(
    expectation_value(ansatz, hamiltonian, IBMQBackend("ibmq_santiago"), 8000))

# For basic practice with using pytket backends and their results, try editing the code here to:
# * Extend `expectation_value` to work with statevector backends (e.g. `AerStateBackend`)
# * Remove the row filtering from `filter_shots` and see the effect on the expectation value on a noisy simulation/device
# * Adapt `filter_shots` to be able to filter a counts dictionary and adapt `expectation_value` to calulate the result using the counts summary from the backend (`pytket.utils.expectation_from_counts` will be useful here)
示例#11
0
ghz_invert_probabilities = probs_from_counts(ghz_invert_corrected_counts)

print(
    "Jensen-Shannon Divergence between noiseless simulation probability distribution and Bayesian-corrected noisy simulation probability distribution: ",
    JSD(ghz_noiseless_probabilities, ghz_spam_corrected_probabilities),
)
print(
    "Jensen-Shannon Divergence between noiseless simulation probability distribution and invert-corrected noisy simulation probability distribution: ",
    JSD(ghz_noiseless_probabilities, ghz_invert_probabilities),
)

# Lets change from our simulator backend to the Santiago IBMQ device to see how SPAM correction performs on real results.

from pytket.extensions.qiskit import IBMQBackend

ibm_backend = IBMQBackend("ibmq_santiago")

santiago_spam_real = SpamCorrecter([ibm_backend.device.nodes], ibm_backend)
ibm_backend.compile_circuit(ghz_circuit)
all_circuits = santiago_spam_real.calibration_circuits() + [ghz_circuit]
ibm_handles = ibm_backend.process_circuits(all_circuits, n_shots)

ibm_calibration_results = (ibm_backend.get_result(handle).get_counts()
                           for handle in ibm_handles[:-1])
santiago_spam_real.calculate_matrices(ibm_calibration_results)

ghz_santiago_counts = ibm_backend.get_result(ibm_handles[-1]).get_counts()
ghz_santiago_probabilities = probs_from_counts(ghz_santiago_counts)

# Finally we compare performance for our machine results: