def deutschJozsa(input_register, black_box): # Take |input_reg> to |input_reg>|1> input_register *= qReg() X.on(input_register, 0) # Prep qubits 1 to n in the Hadamard state. for i in range(1, n + 1): H.on(input_register, i) # Flip the answer qubit and apply H. H.on(input_register, 0) # Query the oracle. black_box.on(input_register, *list(range(n + 1))) # Apply H to the qubits 1 through n. for i in range(1, n + 1): H.on(input_register, i) # Measure the first n qubits. If the any of the results # are nonzero, the oracle is balanced. Else, it is constant. results = [] for i in range(1, n + 1): results.append(input_register.measure(i)) return results
def test_measurement_on_five_qubit_state(self): register = qReg(5) X.on(register, 3) X.on(register, 0) H.on(register, 1) self.assertEqual(register.measure(3), 1) self.assertEqual(register.measure(4), 0)
def test_apply_noisy_gate_with_raised_register(self): ''' Deterministic verification of application of gate with some NoiseModel set (using prob 1 amplitude damping) where qReg needs to be raised. ''' singleQubitInOneStateInitialy = qReg() X.on(singleQubitInOneStateInitialy) self.test_op.set_noise_model(damping_map(1.0)) self.test_op.on(singleQubitInOneStateInitialy, 1) np.testing.assert_array_equal( singleQubitInOneStateInitialy.dump_state(), [0, 1, 0, 0])
def test_apply_noisy_gate(self): ''' Deterministic verification of application of gate with some NoiseModel set (using prob 1 amplitude damping). ''' registerInZeroStateInitially = qReg() registerInOneStateInitially = qReg() X.on(registerInOneStateInitially) self.test_op.set_noise_model(damping_map(1.0)) self.test_op.on(registerInZeroStateInitially) self.test_op.on(registerInOneStateInitially) np.testing.assert_array_equal( registerInZeroStateInitially.dump_state(), [1, 0]) np.testing.assert_array_equal(registerInOneStateInitially.dump_state(), [1, 0])
def test_operator_overloading_misc(self): ''' Tests that several operator overloading methods behave correctly for ``qReg`` objects. ''' temp_reg = qReg() X.on(temp_reg) temp_reg += 1 self.test_reg *= temp_reg state_001 = np.array([0, 1, 0, 0, 0, 0, 0, 0]) np.testing.assert_array_equal(state_001, self.test_reg.dump_state()) temp_reg = qReg() X.on(temp_reg) a_new_reg = self.test_reg * temp_reg state_0011 = np.zeros(16) state_0011[3] = 1 np.testing.assert_array_equal(state_0011, a_new_reg.dump_state())
def test_measure_observable_smaller_than_reg(self): ''' Verifies default behavior of ``qRef.measure_observable()`` is to prefix observable on the left with the identity when ``qReg.size() > observable.size()``. ''' # Make the state 1/sqrt(2) (|100> + |101>) and then measure # I (x) I (x) X. X.on(self.test_reg, 2) H.on(self.test_reg, 0) result = self.test_reg.measure_observable(X) state_hadamard = np.zeros(8) state_hadamard[4] = 1 / np.sqrt(2) state_hadamard[5] = 1 / np.sqrt(2) np.testing.assert_array_almost_equal(state_hadamard, self.test_reg.dump_state()) self.assertEqual(1, result)
def test_known_operation_results(self): ''' Verifies the resulting state of several operations. ''' test_results = [] # Takes |0> to |1> some_reg = qReg() X.on(some_reg) test_results.append(some_reg.dump_state()) # Takes |0> to |0001> some_reg = qReg() X.on(some_reg) I.on(some_reg, 3) test_results.append(some_reg.dump_state()) # Takes |0> to (1/sqrt(2))(|000> - |100>) some_reg = qReg() X.on(some_reg, 2) H.on(some_reg, 2) test_results.append(some_reg.dump_state()) expected_results = [ np.array([0, 1]), np.array([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 1 / np.sqrt(2) * np.array([1, 0, 0, 0, -1, 0, 0, 0]) ] for test_pair in zip(test_results, expected_results): np.testing.assert_array_almost_equal(test_pair[0], test_pair[1])
def test_known_swaps(self): ''' Verifies known swaps in the private ``qOp.__generate_swap()`` method. ''' # Verify that |100> gets swapped to |001> X.on(self.test_reg, 2) swap, inverse_swap = self.test_op._qOp__generate_swap(self.test_reg, 2) state_100 = np.zeros(8) state_100[1] = 1 np.testing.assert_array_equal(state_100, np.dot(swap, self.test_reg.dump_state())) # Verify that |100> gets swapped to |010> with targets 1, 2 swap, inverse_swap = self.test_op._qOp__generate_swap( self.test_reg, 1, 2) state_010 = np.zeros(8) state_010[2] = 1 np.testing.assert_array_equal(state_010, np.dot(swap, self.test_reg.dump_state())) # Verify that (|010> - |011>)/sqrt(2) gets # swapped to (|100> - |101>)/sqrt(2) with targets 0, 2 and 0, 2, 1 for i in range(len(self.test_reg)): X.on(self.test_reg, i) H.on(self.test_reg, 0) swap, inverse_swap = self.test_op._qOp__generate_swap( self.test_reg, 0, 2) np.testing.assert_array_equal( swap, self.test_op._qOp__generate_swap(self.test_reg, 0, 2, 1)[0]) np.testing.assert_array_equal( swap, self.test_op._qOp__generate_swap(self.test_reg, 0, 2)[1]) state_hadamard = np.zeros(8) state_hadamard[4] = 1 / np.sqrt(2) state_hadamard[5] = -1 / np.sqrt(2) np.testing.assert_array_almost_equal( state_hadamard, np.dot(swap, self.test_reg.dump_state()))
def test_known_measurement_results(self): ''' Verifies that the proper post-measurement state occurs in several cases. ''' # Measure |0> correctly self.assertEqual(0, self.test_reg.measure(0)) np.testing.assert_array_equal(np.array([1, 0]), self.test_reg.dump_state()) # Measure |01> correctly self.test_reg += 1 X.on(self.test_reg, 0) self.assertEqual(1, self.test_reg.measure(0)) np.testing.assert_array_equal(np.array([0, 1, 0, 0]), self.test_reg.dump_state()) # Now let's measure the observable X on the # superposition state (|00> - |01>)/sqrt(2). H.on(self.test_reg, 0) self.assertEqual(-1, self.test_reg.measure_observable(I.kron(X)))
def test_register_dereferencing(self): ''' Verifies that ``qReg`` instances get dereferenced in cases where the no-cloning theorem would be violated. ''' # Multiplication operation dereferences register. a = qReg() X.on(a) b = qReg() c = a * b d = qReg() d *= c state_010 = np.zeros(8) state_010[2] = 1 # a, b, and c should all be dereferenced. D should be in |0010> np.testing.assert_array_equal(state_010, d.dump_state()) deref = [a, b, c] for register in deref: # Checks that the dereferenced register is fully dead (i.e. all # methods called with or on it raise an exception. self.assertRaises(IllegalRegisterReference, register.measure, 0) self.assertRaises(IllegalRegisterReference, register.measure_observable, Z) self.assertRaises(IllegalRegisterReference, register.peek) self.assertRaises(IllegalRegisterReference, register.dump_state) self.assertRaises(IllegalRegisterReference, register.__iadd__, 1) self.assertRaises(IllegalRegisterReference, register.__mul__, qReg()) self.assertRaises(IllegalRegisterReference, register.__imul__, qReg()) self.assertRaises(IllegalRegisterReference, len, register) self.assertRaises(IllegalRegisterReference, X.on, register, 0)
import context # Remove this import if running with pip installed version. import numpy as np from pypsqueak.api import qReg, qOp from pypsqueak.gates import X, I from pypsqueak.noise import damping_map import sys # Prep a qReg in the |1> state qubit = qReg() X.on(qubit) # Send it through an amp decay channel with 0.3 chance of decay. if len(sys.argv) > 1 and int(sys.argv[1]) > 0: n_runs = int(sys.argv[1]) else: n_runs = 1000 if len(sys.argv) > 2 and float(sys.argv[2]) >= 0 and float(sys.argv[2]) <= 1: prob = float(sys.argv[2]) else: prob = 0.3 noisy_channel = qOp(kraus_ops=damping_map(prob)) zeros = 0 ones = 0 print("Sending the state |1> through a noisy channel {} times with amplitude decay probability={}...".format(n_runs, prob)) for i in range(n_runs): noisy_channel.on(qubit) result = qubit.measure(0)
# Diagnose error syndrome. Z_21 = Z.kron(Z, I) Z_10 = I.kron(Z, Z) product_21 = super_position.measure_observable(Z_21) # print("Action of Z_21:", super_position.peek()) # print("Z_21 measurement:", product_21) product_10 = super_position.measure_observable(Z_10) # print("Action of Z_10:", super_position.peek()) # print("Z_10 measurement:", product_10) if product_10 == product_21: if product_10 == 1: # No correction required (1 - p)^3 pass else: # Middle qubit flipped (1 - p)^2 * p X.on(super_position, 1) if product_10 != product_21: if product_21 == -1: # Qubit 2 flipped (1 - p)^2 * p X.on(super_position, 2) else: # Qubit 0 flipped (1 - p)^2 * p X.on(super_position, 0) # print("Recovered state:", super_position.peek()) if np.allclose(init_state, super_position.dump_state()): successes += 1 else: failures += 1 print("Successful {:.2f}% of the time".format(100 * successes / n_trials)) print("Unsuccessful {:.2f}% of the time".format(100 * failures / n_trials))