def deutsch_jozsa_algorithm(d, f): # The operators we will need U_f = qc.U_f(f, d=d + 1) H_d = qc.Hadamard(d) H = qc.Hadamard() state = qc.zeros(d) * qc.ones(1) state = (H_d * H)(state) state = U_f(state) state = H_d(state, qubit_indices=range(d)) measurements = state.measure(qubit_indices=range(d)) return measurements
def quantum_teleportation(alice_state): # Get operators we will need CNOT = qc.CNOT() H = qc.Hadamard() X = qc.PauliX() Z = qc.PauliZ() # The prepared, shared Bell state bell = qc.bell_state(0, 0) # The whole state vector state = alice_state * bell # Apply CNOT and Hadamard gate state = CNOT(state, qubit_indices=[0, 1]) state = H(state, qubit_indices=[0]) # Measure the first two bits # The only uncollapsed part of the state vector is Bob's M1, M2 = state.measure(qubit_indices=[0, 1], remove=True) # Apply X and/or Z gates to third qubit depending on measurements if M2: state = X(state) if M1: state = Z(state) return state
def QFT(t): Op = qc.Identity(t) H = qc.Hadamard() # The R_k gate applies a 2pi/2^k phase is the qubit is set C_Rs = {} for k in range(2, t + 1, 1): R_k = np.exp(np.pi * 1j / 2**k) * qc.RotationZ(2 * np.pi / 2**k) C_Rs[k] = qc.ControlledU(R_k) # For each qubit in order, apply the Hadamard gate, and then # apply the R_2, R_3, ... conditional on the remainder of the qubits for t_i in range(t): Op = H(Op, qubit_indices=[t_i]) for k in range(2, t + 1 - t_i, 1): Op = C_Rs[k](Op, qubit_indices=[t_i + k - 1, t_i]) # We have the QFT, but with the qubits in reverse order # Swap them back Swap = qc.Swap() for i, j in zip(range(t), range(t - 1, -1, -1)): if i >= j: break Op = Swap(Op, qubit_indices=[i, j]) return Op
def quantum_parallelism(f): U_f = qc.U_f(f, d=2) H = qc.Hadamard() phi = qc.zeros(2) phi = H(phi, qubit_indices=[0]) phi = U_f(phi)
def test_CNOT_hadamard_identity(self): C = qc.CNOT() H = qc.Hadamard() C1 = (H * H)(C(H * H, qubit_indices=[1, 0])) self.assertLess(max_absolute_difference(C, C1), epsilon)
def bell_state(x, y): H = qc.Hadamard() CNOT = qc.CNOT() phi = qc.bitstring(x, y) phi = H(phi, qubit_indices=[0]) return CNOT(phi)
def deutsch_algorithm(f): U_f = qc.U_f(f, d=2) H = qc.Hadamard() phi = H(qc.zeros()) * H(qc.ones()) phi = U_f(phi) phi = H(phi, qubit_indices=[0]) measurement = phi.measure(qubit_indices=0) return measurement
def test_hadamard_pauli_identities(self): X = qc.PauliX() Y = qc.PauliY() Z = qc.PauliZ() H = qc.Hadamard() self.assertLess(max_absolute_difference(H(X(H)), Z), epsilon) self.assertLess(max_absolute_difference(H(Z(H)), X), epsilon) self.assertLess(max_absolute_difference(H(Y(H)), -Y), epsilon) self.assertLess(max_absolute_difference(X(Y(X)), -Y), epsilon)
def grover_algorithm(d, f): # The operators we will need Oracle = qc.U_f(f, d=d+1) H_d = qc.Hadamard(d) H = qc.Hadamard() N = 2**d zero_projector = np.zeros((N, N)) zero_projector[0, 0] = 1 Inversion = H_d((2 * qc.Operator.from_matrix(zero_projector) - qc.Identity(d))(H_d)) Grover = Inversion(Oracle, qubit_indices=range(d)) # Initial state state = qc.zeros(d) * qc.ones(1) state = (H_d * H)(state) # Number of Grover iterations angle_to_rotate = np.arccos(np.sqrt(1 / N)) rotation_angle = 2 * np.arcsin(np.sqrt(1 / N)) iterations = int(round(angle_to_rotate / rotation_angle)) for i in range(iterations): state = Grover(state) measurements = state.measure(qubit_indices=range(d)) return measurements
def stage_1(state, U, t, d): state = qc.Hadamard(d=t)(state, qubit_indices=range(t)) # For each qubit in reverse order, apply the Hadamard gate, # then apply U^(2^i) to the d-qubit register # conditional on the state of the t-i qubit in the # t-qubit register. for idx, t_i in enumerate(range(t - 1, -1, -1)): U_2_idx = U for app_i in range(idx): U_2_idx = U_2_idx(U_2_idx) C_U = qc.ControlledU(U_2_idx) state = C_U(state, qubit_indices=[t_i] + list(range(t, t + d, 1))) return state
def test_hadamard(self): """ H = (X + Y)/sqrt(2) """ H = qc.Hadamard() X = qc.PauliX() Z = qc.PauliZ() H1 = (X + Z) / np.sqrt(2) max_diff = max_absolute_difference(H, H1) self.assertLess(max_diff, epsilon) H2 = (X + Z) * (1 / np.sqrt(2)) max_diff = max_absolute_difference(H, H2) self.assertLess(max_diff, epsilon) H3 = 1 / np.sqrt(2) * (Z + X) max_diff = max_absolute_difference(H, H3) self.assertLess(max_diff, epsilon) self.assertLess(max_absolute_difference(np.sqrt(2) * H - Z, X), epsilon)
def test_phase_identities(self): Z = qc.PauliZ() S = qc.Phase() T = qc.PiBy8() H = qc.Hadamard() self.assertLess(max_absolute_difference(T(T), S), epsilon) self.assertLess(max_absolute_difference(S(S), Z), epsilon) self.assertLess(max_absolute_difference(T(T(T(T))), Z), epsilon) self.assertLess( max_absolute_difference( T, np.exp(1j * np.pi / 8) * qc.RotationZ(np.pi / 4)), epsilon) self.assertLess( max_absolute_difference( S, np.exp(1j * np.pi / 4) * qc.RotationZ(np.pi / 2)), epsilon) self.assertLess( max_absolute_difference( H(T(H)), np.exp(1j * np.pi / 8) * qc.RotationX(np.pi / 4)), epsilon)
def superdense_coding(bit_1, bit_2): # Get operators we will need CNOT = qc.CNOT() H = qc.Hadamard() X = qc.PauliX() Z = qc.PauliZ() # The prepared, shared Bell state # Initially, half is in Alice's possession, and half in Bob's phi = qc.bell_state(0, 0) # Alice manipulates her qubit if bit_2: phi = X(phi, qubit_indices=[0]) if bit_1: phi = Z(phi, qubit_indices=[0]) # Bob decodes the two bits phi = CNOT(phi) phi = H(phi, qubit_indices=[0]) measurements = phi.measure() return measurements