Beispiel #1
0
def interference(repeat_count: int, starting_state: int) -> dict[tuple[int, ...], int]:
    """Creates a superposition and applies interference on a qubit in a specified state a specified number of times.

    Args:
        repeat_count (int): The number of times to repeat the quantum circuit.
        starting_state (int): The state to set the qubit to prior to running the quantum circuit.

    Returns:
        dict[tuple[int, ...], int]: The measurement result counts.
    """
    # Set up quantum circuit with 1 qubit and 1 bit.
    # Set qubit to desired starting state.
    # If the starting state should be 1, apply the X gate.
    circuit = Circuit(1, 1)
    if starting_state == 1:
        circuit.X(0)
    
    # Apply Hadamard gate to create a superposition.
    circuit.H(0)

    # Apply Hadamard gate to cause interference to restore qubit to its starting state.
    circuit.H(0)

    # Measure the qubit and save the result into a classical bit.
    circuit.Measure(0, 0)

    # Initialise backend and run circuit a specified number of times.
    backend.compile_circuit(circuit)
    job = backend.process_circuit(circuit, n_shots=repeat_count)

    # Get counts of qubit measurement results.
    result_counts = backend.get_result(job).get_counts()
    return result_counts
def test_expectation_value() -> None:
    c = Circuit(2)
    c.H(0)
    c.CX(0, 1)
    op = QubitPauliOperator({
        QubitPauliString({
            Qubit(0): Pauli.Z,
            Qubit(1): Pauli.Z
        }):
        1.0,
        QubitPauliString({
            Qubit(0): Pauli.X,
            Qubit(1): Pauli.X
        }):
        0.3,
        QubitPauliString({
            Qubit(0): Pauli.Z,
            Qubit(1): Pauli.Y
        }):
        0.8j,
        QubitPauliString({Qubit(0): Pauli.Y}):
        -0.4j,
    })
    b = MyBackend()
    b.compile_circuit(c)
    assert get_operator_expectation_value(c, op, b) == pytest.approx(1.3)
def test_sampler_expectation_value() -> None:
    c = Circuit(2)
    c.H(0)
    c.CX(0, 1)
    op = QubitPauliOperator({
        QubitPauliString({
            Qubit(0): Pauli.Z,
            Qubit(1): Pauli.Z
        }):
        1.0,
        QubitPauliString({
            Qubit(0): Pauli.X,
            Qubit(1): Pauli.X
        }):
        0.3,
        QubitPauliString({
            Qubit(0): Pauli.Z,
            Qubit(1): Pauli.Y
        }):
        0.8j,
        QubitPauliString({Qubit(0): Pauli.Y}):
        -0.4j,
    })
    b = MySampler()
    b.compile_circuit(c)
    expectation = get_operator_expectation_value(c,
                                                 op,
                                                 b,
                                                 n_shots=2000,
                                                 seed=0)
    assert (np.real(expectation), np.imag(expectation)) == pytest.approx(
        (1.3, 0.0), abs=0.1)
def test_sampler_invalid_conditions() -> None:
    c = Circuit(2, 2)
    c.H(0)
    c.CX(0, 1, condition_bits=[0, 1], condition_value=3)
    c.measure_all()
    b = MySampler()
    b.compile_circuit(c)
    assert not (b.valid_circuit(c))
def test_bell() -> None:
    c = Circuit(2)
    c.H(0)
    c.CX(0, 1)
    b = MyBackend()
    b.compile_circuit(c)
    assert np.allclose(b.get_state(c),
                       np.asarray([1, 0, 0, 1]) * 1 / np.sqrt(2))
def test_sampler_bell() -> None:
    c = Circuit(2, 2)
    c.H(0)
    c.CX(0, 1)
    c.measure_all()
    b = MySampler()
    b.compile_circuit(c)
    assert b.get_shots(c, n_shots=10, seed=3).shape == (10, 2)
    assert b.get_counts(c, n_shots=10, seed=3) == {(0, 0): 5, (1, 1): 5}
Beispiel #7
0
def U(s, n_qubits):
    c = Circuit(n_qubits)
    for i in range(len(s)):
        if s[i] == "X":
            c.H(i)
        elif s[i] == "Y":
            c.Rx(i, 0.5)
        elif s[i] == "Z":
            pass
    return c
Beispiel #8
0
def add_operator_term(circuit: Circuit, term: QubitPauliString, angle: float):
    qubits = []
    for q, p in term.to_dict().items():
        if p != Pauli.I:
            qubits.append(q)
            if p == Pauli.X:
                circuit.H(q)
            elif p == Pauli.Y:
                circuit.V(q)
    for i in range(len(qubits) - 1):
        circuit.CX(i, i + 1)
    circuit.Rz(angle, len(qubits) - 1)
    for i in reversed(range(len(qubits) - 1)):
        circuit.CX(i, i + 1)
    for q, p in term.to_dict().items():
        if p == Pauli.X:
            circuit.H(q)
        elif p == Pauli.Y:
            circuit.Vdg(q)
Beispiel #9
0
def pauli_measurement(pauli_string:Iterable[Tuple[int,str]], circ:Circuit) :
    """Appends measurement instructions to a given circuit, measuring each qubit in a given basis

    
    :param pauli_string: The pauli operator to measure, as tuples of pauli name and qubit.
    :type pauli_string: Iterable[Tuple[int,str]]
    :param circ: Circuit to add measurement to.
    :type circ: Circuit
    """
    measured_qbs = []
    for qb_idx, p in pauli_string:
        measured_qbs.append(qb_idx)
        if p=='X':
            circ.H(qb_idx)
        elif p=='Y':
            circ.Sdg(qb_idx)
            circ.H(qb_idx)

    for idx in measured_qbs:
        circ.Measure(idx, idx)
Beispiel #10
0
def measure_x(quantum_circuit: Circuit, qubit: int, bit: int) -> None:
    """Measures a specified qubit in the Hadamard (X) basis.

    Args:
        quantum_circuit (pytket.circuit.Circuit): The quantum circuit to apply the measurement to.
        qubit (int): The qubit to measure.
        bit (int): The bit to save the qubit measurement result into.
    """
    # Apply Hadamard gate to the qubit.
    # Measure the qubit into the bit.
    quantum_circuit.H(qubit)
    quantum_circuit.Measure(qubit, bit)
def pauli_evolution(pauli: List[Tuple[int, str]], coeff: complex, circ: Circuit):
   """Appends the evolution circuit corresponding to a given Pauli tensor

   Args:
       pauli:
       coeff (complex):
       circ (Circuit):
   """
   # set up the correct basis
   all_qbs = list(zip(*pauli))[0]
   for qb_idx, p in pauli:
       if p == 'X':
           circ.H(qb_idx)
       elif p == 'Y':
           # angles in half-turns
           circ.Rx(qb_idx, 0.5)

   # cnot cascade
   cx_qb_pairs = list(zip(sorted(all_qbs)[:-1], sorted(all_qbs)[1:]))
   for pair in cx_qb_pairs:
       circ.CX(pair[0], pair[1])

   # rotation (convert angle from radians to half-turns)
   circ.Rz(all_qbs[-1], (2 * coeff.imag) / PI)

   # reverse cascade and revert basis
   cx_qb_pairs = list(zip(sorted(all_qbs)[:-1], sorted(all_qbs)[1:]))
   for pair in reversed(cx_qb_pairs):
       circ.CX(pair[0], pair[1])

   all_qbs = list(zip(*pauli))[0]

   for qb_idx, p in pauli:
       if p == 'X':
           circ.H(qb_idx)
       elif p == 'Y':
           circ.Rx(qb_idx, -0.5)
Beispiel #12
0
def measurement_circuits(hamiltonian, n_qubits):
    all_circs = []
    for pauli, _ in hamiltonian.terms.items():
        if not pauli:
            continue  # Ignore the constant term
        measure_circ = Circuit(n_qubits, n_qubits)
        for qb, p in pauli:
            if p == 'I':
                continue  # Discard I qubits
            elif p == 'X':
                measure_circ.H(qb)
            elif p == 'Y':
                measure_circ.Rx(0.5, qb)
            measure_circ.Measure(qb, qb)
        all_circs.append(measure_circ)
    return all_circs
Beispiel #13
0
def generate_random_number() -> int:
    """Generates a random number between 0-15.

    Returns:
        int: A random number between 0-15.
    """
    # Set up quantum circuit with 4 qubits.
    circuit = Circuit(4, 4)

    # Apply Hadamard gate to all qubits.
    for qubit in range(4):
        circuit.H(qubit)

    # Measure all qubits.
    circuit.measure_all()

    # Initialise simulator and run circuit.
    job = backend.process_circuit(circuit, n_shots=1)
    shots = backend.get_result(job).get_shots()

    # Get shot measurement results and convert result as binary digits into integer.
    random_number_bitstring = ''.join(list(map(str, shots[0])))
    random_number = int(f'0b{random_number_bitstring}', 2)
    return random_number
Beispiel #14
0
def superposition(repeat_count: int, basis_measurement: Callable[[Circuit, int, int], None]) -> dict[tuple[int, ...], int]:
    """Creates a superposition and measures it using a specified basis a specified number of times.

    Args:
        repeat_count (int): The number of times to repeat the quantum circuit.
        basis_measurement (Callable[[Circuit, int, int], None]): The function to perform the specified basis measurement with.

    Returns:
        dict[tuple[int, ...], int]: The measurement result counts.
    """
    # Set up quantum circuit with 1 qubit and 1 bit.
    # Apply Hadamard gate to qubit 0.
    # Measure qubit 0 into bit 0 using the specified measurement basis.
    circuit = Circuit(1, 1)
    circuit.H(0)
    basis_measurement(circuit, 0, 0)

    # Initialise backend and run circuit a specified number of times.
    backend.compile_circuit(circuit)
    job = backend.process_circuit(circuit, n_shots=repeat_count)

    # Get counts of qubit measurement results.
    result_counts = backend.get_result(job).get_counts()
    return result_counts
Beispiel #15
0
def iterated_entanglement_swap(n_iter):
    # Iterate the entanglement swapping protocol n_iter times
    it_es = Circuit()
    ava = it_es.add_q_register("a", 1)
    bella = it_es.add_q_register("b", 2)
    charlie = it_es.add_q_register("c", 1)
    data = it_es.add_c_register("d", 2)

    # Start with an initial Bell state
    it_es.H(ava[0])
    it_es.CX(ava[0], bella[0])

    for i in range(n_iter):
        if i % 2 == 0:
            # Teleport bella[0] to charlie[0] to give a Bell pair between ava[0] and charlier[0]
            tel_to_c = qtel.copy()
            tel_to_c.rename_units(
                {alice[0]: bella[0], alice[1]: bella[1], bob[0]: charlie[0]}
            )
            it_es.append(tel_to_c)
            it_es.add_gate(OpType.Reset, [bella[0]])
            it_es.add_gate(OpType.Reset, [bella[1]])
        else:
            # Teleport charlie[0] to bella[0] to give a Bell pair between ava[0] and bella[0]
            tel_to_b = qtel.copy()
            tel_to_b.rename_units(
                {alice[0]: charlie[0], alice[1]: bella[1], bob[0]: bella[0]}
            )
            it_es.append(tel_to_b)
            it_es.add_gate(OpType.Reset, [bella[1]])
            it_es.add_gate(OpType.Reset, [charlie[0]])
    # Return the circuit and the qubits expected to share a Bell pair
    if n_iter % 2 == 0:
        return it_es, [ava[0], bella[0]]
    else:
        return it_es, [ava[0], charlie[0]]
Beispiel #16
0
    # Apply Hadamard gate to the qubit.
    # Measure the qubit into the bit.
    quantum_circuit.H(qubit)
    quantum_circuit.Measure(qubit, bit)


print('*** Hello, Quantum! - Phase Kickback (tket) ***')

repeat_count = 1000

# Set up cirbuit with 2 qubits and 2 classical bits.
circuit = Circuit(2, 2)

# Apply Hadamard gate to control qubit to create a superposition in the
# (+)-superposition state.
circuit.H(0)

# Apply X gate to target qubit to set it to the 1 state.
# Apply Hadamard gate to target qubit to create a superposition in the
# (-)-superposition state.
circuit.X(1)
circuit.H(1)

# Apply CNOT gate to target qubit using the control qubit to trigger phase
# kickback onto the control qubit.
circuit.CX(0, 1)

# Measure qubits in the Hadamard (X) basis.
measure_x(circuit, 0, 0)
measure_x(circuit, 1, 1)
Beispiel #17
0
sys.path.append('../../../libraries')
from tket_backend_factory import get_tket_backend

# Get quantum backend from command-line arguments.
backend = get_tket_backend()

print('*** Hello, Quantum! - Entanglement (tket) ***')

repeat_count = 1000

# Set up cirbuit with 2 qubits and 2 classical bits.
# Apply Hadamard gate to the control qubit 0.
# Apply Controlled NOT gate to the target qubit 1 using qubit 0 as control.
# Measure the qubits and save the result into classical bits.
circuit = Circuit(2, 2)
circuit.H(0)
circuit.CX(0, 1)
circuit.Measure(0, 0)
circuit.Measure(1, 1)

# Initialise backend and run circuit a specified number of times.
backend.compile_circuit(circuit)
job = backend.process_circuit(circuit, n_shots=repeat_count)

# Get counts of qubit measurement results.
result_counts = backend.get_result(job).get_counts()

# Print results.
print(f"Counts for {repeat_count} repeats:")
print(f"\t00: {result_counts[(0, 0)]}")
print(f"\t01: {result_counts[(0, 1)]}")
Beispiel #18
0
# `if(c==3) z b[0];`
# `if(c==2) x b[0];`
# `if(c==3) x b[0];`
#
# This corresponds to the following `pytket` code:

from pytket import Circuit

qtel = Circuit()
alice = qtel.add_q_register("a", 2)
bob = qtel.add_q_register("b", 1)
data = qtel.add_c_register("d", 2)

# Bell state between Alice and Bob:

qtel.H(alice[1])
qtel.CX(alice[1], bob[0])

# Bell measurement of Alice's qubits:

qtel.CX(alice[0], alice[1])
qtel.H(alice[0])
qtel.Measure(alice[0], data[0])
qtel.Measure(alice[1], data[1])

# Correction of Bob's qubit:

qtel.X(bob[0], condition_bits=[data[0], data[1]], condition_value=2)
qtel.X(bob[0], condition_bits=[data[0], data[1]], condition_value=3)
qtel.Z(bob[0], condition_bits=[data[0], data[1]], condition_value=1)
qtel.Z(bob[0], condition_bits=[data[0], data[1]], condition_value=3)
Beispiel #19
0
def test_invalid_measures() -> None:
    c = Circuit(2)
    c.H(0).CX(0, 1).measure_all()
    b = MyBackend()
    b.compile_circuit(c)
    assert not (b.valid_circuit(c))
backend = AerBackend()
backend.compile_circuit(c)
handle = backend.process_circuit(c, n_shots=2000)
counts = backend.get_result(handle).get_counts()
print(counts)

# ## Statevector simulator usage

from pytket import Circuit
from pytket.extensions.qiskit import AerStateBackend

# Build a quantum state:

c = Circuit(3)
c.H(0).CX(0, 1)
c.Rz(0.3, 0)
c.Rz(-0.3, 1)
c.Ry(0.8, 2)

# Examine the statevector:

backend = AerStateBackend()
backend.compile_circuit(c)
handle = backend.process_circuit(c)
state = backend.get_result(handle).get_state()
print(state)

# ## Expectation value usage

from pytket import Circuit, Qubit