Exemple #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
Exemple #2
0
def measure_z(quantum_circuit: Circuit, qubit: int, bit: int) -> None:
    """Measures a specified qubit in the Computational (Z) 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.
    """
    # Measure the qubit into the bit.
    quantum_circuit.Measure(qubit, bit)
Exemple #3
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 test_transpile_1q_circuit(self):
     c = Circuit(1, 1)
     c.Rz(1, 0)
     c.add_barrier([0])
     c.Measure(0, 0)
     qsc = jaqal_circuit_from_tket_circuit(c)
     jcirc = CircuitBuilder()
     reg = jcirc.register("baseregister", 1)
     reg2 = jcirc.map("q", reg, slice(0, 1, 1))
     block = jcirc.block()
     block.gate("prepare_all")
     block.gate("Rz", reg2[0], pi)
     block = jcirc.block()
     block.gate("measure_all")
     self.assertEqual(generate_jaqal_program(jcirc.build()),
                      generate_jaqal_program(qsc))
Exemple #5
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
Exemple #6
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)
Exemple #7
0
# Ideally the state generated by this ansatz will only span the computational basis states with exactly two of the four qubits in state $\lvert 1 \rangle$. This is because these basis states correspond to two electrons being present in the molecule.
#
# This ansatz is a hardware-efficient model that is designed to explore a large portion of the Hilbert space with relatively few entangling gates. Unfortunately, with this much freedom, it will regularly generate states that have no physical interpretation such as states spanning multiple basis states corresponding to different numbers of electrons in the system (which we assume is fixed and conserved).
#
# We can mitigate this by using a syndrome qubit that calculates the parity of the other qubits. Post-selecting this syndrome with $\langle 0 \rvert$ will project the remaining state onto the subspace of basis states with even parity, increasing the likelihood the observed state will be a physically admissible state.
#
# Even if the ansatz parameters are tuned to give a physical state, real devices have noise and imperfect gates, so in practice we may also measure bad states with a small probability. If this syndrome qubit is measured as 1, it means an error has definitely occurred, so we should discard the shot.

syn = Qubit("synq", 0)
syn_res = Bit("synres", 0)
ansatz.add_qubit(syn)
ansatz.add_bit(syn_res)
for qb in qubits:
    ansatz.CX(qb, syn)
ansatz.Measure(syn, syn_res)

# Using this, we can define a filter function which removes the shots which the syndrome qubit detected as erroneous. `BackendResult` objects allow retrieval of shots in any bit order, so we can retrieve the `synres` results separately and use them to filter the shots from the remaining bits. The Backends example notebook describes this in more detail.


def filter_shots(backend_result, syn_res_bit):
    bits = sorted(backend_result.get_bitlist())
    bits.remove(syn_res_bit)
    syn_shots = backend_result.get_shots([syn_res])[:, 0]
    main_shots = backend_result.get_shots(bits)
    return main_shots[syn_shots == 0]
    filtered_rows = shot_table[shot_table[:, syn_res_index] == 0]
    return np.delete(filtered_rows, syn_res_index, axis=1)


# Depending on which backend we will be using, we will need to compile each circuit we run to conform to the gate set and connectivity constraints. We can define a compilation pass for each backend that optimises the circuit and maps it onto the backend's gate set and connectivity constraints. We don't expect this to change our circuit too much as it is already near-optimal.
Exemple #8
0
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)

# So to demonstrate the Entanglement Swapping protocol, we just need to run this on one side of a Bell pair.

es = Circuit()
ava = es.add_q_register("a", 1)
bella = es.add_q_register("b", 2)
charlie = es.add_q_register("c", 1)
Exemple #9
0
# 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)]}")
print(f"\t10: {result_counts[(1, 0)]}")
print(f"\t11: {result_counts[(1, 1)]}")
bob = c.add_q_register("b", 1)
data = c.add_c_register("d", 2)
final = c.add_c_register("f", 1)

# Start in an interesting state:

c.Rx(0.3, alice[0])

# Set up a Bell state between Alice and Bob:

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

# Measure Alice's qubits in the Bell basis:

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

# Correct Bob's qubit:

c.X(bob[0], condition_bits=[data[0], data[1]], condition_value=1)
c.X(bob[0], condition_bits=[data[0], data[1]], condition_value=3)
c.Z(bob[0], condition_bits=[data[0], data[1]], condition_value=2)
c.Z(bob[0], condition_bits=[data[0], data[1]], condition_value=3)

# Measure Bob's qubit to observe the interesting state:

c.Measure(bob[0], final[0])

# Set up a noisy simulator: