def test_collision_probability(): """ Test cases for the collision probability algorithm Returns True if passed all test cases, otherwise returns False """ print("Testing: collision probability algorithm") # n = number of qubits, m = size of qubit gate for n in range(1, 10): # sim1 is fast and sim2 is slow, as sim2 uses exponential # storage and runtime sim1 = chp_py.CHP_Simulation(n) sim2 = slow_sim.Slow_Simulation(n) for m in range(1, min(n, 5)): for j in range(100): # Get a random symplectic of size 2m x 2m i = np.random.randint(symplectic.numberofsymplectic(m)) S = symplectic.symplectic(i, m) S = decompose.transform_symplectic(S) # Get m random qubits qubits = np.arange(m) np.random.shuffle(qubits) qubits = qubits[:m] # Get the gates and matrix represention of S gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S)) gates = decompose.change_gates(gates, qubits) decompose.apply_gates(gates, sim1) decompose.apply_gates(gates, sim2) k_1 = int(-sim1.log_collision_probability) k_2 = np.round(-np.log2(sim2.collision_probability)) result = (k_1 == k_2) if not result: print("Failed: collision probability algorithm returned " + "incorrect result with n = " + str(n) + " and m = " + str(m)) return False print("Passed: collision probability algorithm passed all tests\n") return True
def test_chp_py(): """ Test cases for the functions in chp_py.py Returns True if passed all test cases, otherwise returns False """ print("Testing: chp_py.py") # n = number of qubits, m = size of qubit gate for n in range(1, 50): # Create two simulations # sim1 uses decomposed gates and sim2 uses matrix multiplication # apply 100 random gates to each one sim1 = chp_py.CHP_Simulation(n) sim2 = chp_py.CHP_Simulation(n) for m in range(1, min(n, 5)): for j in range(100): # Get a random symplectic of size 2m x 2m i = np.random.randint(symplectic.numberofsymplectic(m)) S = symplectic.symplectic(i, m) S = decompose.transform_symplectic(S) # Get m random qubits qubits = np.arange(m) np.random.shuffle(qubits) qubits = qubits[:m] # Get the gates and matrix represention of S gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S)) gates = decompose.change_gates(gates, qubits) M = decompose.symplectic_to_matrix(S, n, qubits) sim1.apply_gates(gates) sim2.state = (sim2.state @ M) % 2 result = (sim1.state == sim2.state).all() if not result: print("Failed: found two simulations with different " + "states for n = " + str(n)) return False print("Passed: chp_py.py passed all tests\n") return True
def simulate_qubit_pairs_1D_lattice(n, m): """ Simulates a set of qubits in a 1D lattice of n qubits Performs two seperate rounds when applying gates to ensure that the depth of the circuit is accurate Runs the simulation a total of m times and returns the mean and std in the data dictionary """ # Initialize some variables x_max = 2 * n d = np.linspace(0, x_max, 50, dtype=int) k_matrix = np.zeros((m, len(d))) # Run the simulation a total of m times for i in range(m): start = time.time() sim = chp_py.CHP_Simulation(n) sims = [] # Add a sim for depth 0 sims.append(chp_py.CHP_Simulation(n, sim.state)) for j in range(0, d[-1]): gates = utils.get_lattice_gates((n, ), j) sim.apply_gates(gates) if j + 1 in d: sims.append(chp_py.CHP_Simulation(n, sim.state)) # This computes the collision_probability at different # depths in parallel k_matrix[i, :] = utils.sims_to_collision_probabilty(sims) end = time.time() print("Time elapsed = {:0.2f}, for sample = {}".format(end - start, i)) # Store everything in data data = {"d": d, "k_matrix": k_matrix, "n": n, "m": m} return data
def simulate_complete_graph(n, m): """ Simulates qubits in a complete graph of n qubits Find k as a function of N = number of gates applied Performs simulation a total of m times then returns mean and std """ x_max = 2 * n * np.log(n) N = np.linspace(0, x_max, 50, dtype=int) k_matrix = np.zeros((m, len(N))) # Run the simulation a total of m times for i in range(m): start = time.time() sim = chp_py.CHP_Simulation(n) sims = [] # Add a sim for N = 0 sims.append(chp_py.CHP_Simulation(n, sim.state)) for j in range(0, N[-1]): qubits = np.arange(n) np.random.shuffle(qubits) q_1, q_2 = qubits[:2] gates = utils.get_random_two_qubit_gate(q_1, q_2) sim.apply_gates(gates) if j + 1 in N: sims.append(chp_py.CHP_Simulation(n, sim.state)) # This computes the collision_probability at different # depths in parallel k_matrix[i, :] = utils.sims_to_collision_probabilty(sims) end = time.time() print("Time elapsed = {:0.2f}, for sample = {}".format(end - start, i)) # Store everything in data data = {"N": N, "k_matrix": k_matrix, "n": n, "m": m} return data
def test_decompose(): """ Test cases for the functions in decompose.py Returns True if passed all test cases, otherwise returns False """ print("Testing: decompose.py") for n in range(1, 6): top = np.hstack((np.zeros((n, n)), np.identity(n))) bottom = np.hstack((np.identity(n), np.zeros((n, n)))) L = np.vstack((top, bottom)) for j in range(500): # Get a random symplectic i = np.random.randint(symplectic.numberofsymplectic(n)) S = symplectic.symplectic(i, n) S = decompose.transform_symplectic(S) # Make sure the transformation worked result = (S.T @ L @ S) % 2 result = ((result == L).all()) if not result: print("Failed: could not transform symplectic " + "matrix with (n, i)= " + str((n, i))) return False # Make sure we can decompose it # Applying the decomposed gates to the identity should give us S gates = decompose.decompose_state(chp_py.CHP_Simulation(n, S)) new_sim = chp_py.CHP_Simulation(n) new_sim.apply_gates(gates) result = (new_sim.state == S).all() if not result: print("Failed: found a bad decomposition for " + "symplectic matrix with (n, i)= " + str((n, i))) return False print("Passed: decompose.py passed all tests\n") return True
def simulate_qubit_pairs_2D_lattice(sqrt_n, m): """ Simulates a set of qubits in a 2D square lattice of shape sqrt_n x sqrt_n. Performs four seperate rounds when applying gates to ensure that the depth of the circuit is accurate Runs the simulation a total of m times and returns the mean and std in the data dictionary """ # Initialize some variables n = np.power(sqrt_n, 2) x_max = 35 d = np.arange(0, x_max + 1) k_matrix = np.zeros((m, x_max + 1)) # Run the simulation a total of m times for i in range(m): start = time.time() sim = chp_py.CHP_Simulation(n) sims = [] # Add a sim for depth 0 sims.append(chp_py.CHP_Simulation(n, sim.state)) for j in range(x_max): gates = utils.get_lattice_gates((sqrt_n, sqrt_n), j) sim.apply_gates(gates) sims.append(chp_py.CHP_Simulation(n, sim.state)) # This computes the collision_probability at different # depths in parallel k_matrix[i, :] = utils.sims_to_collision_probabilty(sims) end = time.time() print("Time elapsed = {:0.2f}, for sample = {}".format(end - start, i)) # Store everything in data data = {"d": d, "k_matrix": k_matrix, "n": n, "m": m} return data
def store_all_two_qubit_gates(): m = 2 qubit_gates = dict() qubit_matrices = dict() for i in range(symplectic.numberofsymplectic(m)): S = symplectic.symplectic(i, m) S = decompose.transform_symplectic(S) gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S)) qubit_gates[i] = gates qubit_matrices[i] = S save_data(qubit_gates, "two_qubit_gates") save_data(qubit_matrices, "two_qubit_matrices")
def test_stored_two_qubit_gates(): """ Test cases for the stored two_qubit_gates Returns True if passed all test cases, otherwise returns False """ print("Testing: stored two qubit gates") utils.store_all_two_qubit_gates() two_qubit_gates = utils.load_data("two_qubit_gates") two_qubit_matrices = utils.load_data("two_qubit_matrices") matrices = set() for i in two_qubit_gates: # Make sure the gates and matrices have the same effect gates = two_qubit_gates[i] M = two_qubit_matrices[i] sim1 = chp_py.CHP_Simulation(2) sim1.apply_gates(gates) # Also store the matrices in a set M_string = str(M.flatten()) matrices.add(M_string) result = (sim1.state == M).all() if not result: print("Failed: two qubit gates do not agree with " + "two qubit matrix for i = " + str(i)) return False # Make sure we have the right number of unique matrices result = (len(matrices) == symplectic.numberofsymplectic(2)) if not result: print("Failed: did not find the correct number of unique " + "two qubit matrices") return False print("Passed: stored two qubit gates passed all tests\n") return True