def superposition(repeat_count, basis_measurement): """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 program. basis_measurement (function): The function to perform the specified basis measurement with. Returns: int: The measurement count where the result is 1. """ program = Program() program += H(0) basis_measurement(program, 0) with local_forest_runtime(): # Initialise simulator and run circuit a specified number of times. quantum_virtual_machine = get_qc('9q-square-qvm') qubit_result_counts = quantum_virtual_machine.run_and_measure( program, trials=repeat_count) # Loop through results and update count if result is 1. ones_count = 0 for result in qubit_result_counts[0]: if result == 1: ones_count += 1 return ones_count
def generate_random_number(): """Generates a random number between 0-15. Returns: int: A random number between 0-15. """ # Initialise program. # Apply Hadamard gate to 4 qubits. program = Program() for qubit in range(4): program += H(qubit) with local_forest_runtime(): # Initialise simulator and run circuit a specified number of times. # Get counts of qubit measurement results, which is a single result with 1 count. quantum_virtual_machine = get_qc('9q-square-qvm') qubit_result_counts = quantum_virtual_machine.run_and_measure(program, trials=1) # Convert result as binary digits into bit-string. result_bitstring = '0b' for result in range(4): result_bitstring += str(qubit_result_counts[result][0]) # Convert bit-string as binary digits into integer. random_number = int(result_bitstring, 2) return random_number
def interference(repeat_count, starting_state): """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: int: The measurement count where the result is 1. """ # Initialise program. # Set qubit to desired starting state. # If the starting state should be 1, apply the X gate. program = Program() if starting_state == 1: program += X(0) # Apply Hadamard gate to create a superposition. program += H(0) # Apply Hadamard gate to cause interference to restore qubit to its starting state. program += H(0) with local_forest_runtime(): # Initialise simulator and run circuit a specified number of times. quantum_virtual_machine = get_qc('9q-square-qvm') qubit_result_counts = quantum_virtual_machine.run_and_measure(program, trials=repeat_count) # Loop through results and update count if result is 1. ones_count = 0 for result in qubit_result_counts[0]: if result == 1: ones_count += 1 return ones_count
def local_qvm_quilc(): """Execute test with local qvm and quilc running""" if shutil.which('qvm') is None or shutil.which('quilc') is None: return pytest.skip("This test requires 'qvm' and 'quilc' " "executables to be installed locally.") with local_forest_runtime() as context: yield context
def solve(self): with local_forest_runtime(): qc = get_qc('9q-square-qvm') result = qc.run_and_measure(self.__p, trials = 1) a = '' for i in range(self.n): a+=str(result[i][0]) return a
def simons_algorithm(f, n): """ Inputs: f is a blackbox function (f:{0,1}^n -> {0,1}^n) that is either one-to-one or two-to-onw. n is the dimension of the input into f. This function finds and returns the key s, if one exists, for a two=to-one function by first creating a matrix U_f that represents f, then applying the appropriate quantum gates to generate a linear equation. By running the circuit n-1 times, we generate n-1 equations that we then feed into a classical solver. The Classical solver returns s. Returns: the key string s, if found, or the zero bitstring """ # Initialize the program and apply the Hadamard gate to the first n qubits. program = initialize([0] * n) # Initialize an extra n bits by applying the Identity gate. for index in range(n, (2 * n)): program += I(index) # Generate the U_f gate for f uf_simons_gate = generate_uf_simons(f, n, "Uf_Simons") Uf_simons = uf_simons_gate.get_constructor() # Initialize qubits and apply the U_f gate to all qubits qubits = list(range(2 * n)) program += uf_simons_gate program += Uf_simons(*qubits) # Pick the qubits to which to apply the final Hadamard gates. apply_to_list = [1] * n np.append(apply_to_list, [0] * n) program = apply_H(program, apply_to_list) with local_forest_runtime(): qvm = get_qc('9q-square-qvm') s_trials = list() # Conduct 20 trials of the algorithm - it's not deterministic for i in range(20): # Run the circuit n-1 times to generate n-1 equations measurements = qvm.run_and_measure(program, trials=n - 1) Y = np.zeros((n - 1, n)) # Parse the resulting relevant measurements from the circuit and store in a matrix for index in range(n): for j in range(len(measurements[index])): Y[j][index] = measurements[index][j] # Plug Y into the binary matrix solver and store in a list of possible s strings (s_trials) s_primes = simons_solver(Y, n) s_trials.append(s_primes) # Check if each s satisfies the condition needed to be a 'key' and return it if the condition is met for trial in s_trials: if (f([0] * n) == f(trial)): return trial # If no such s is found, return the 0 bitstring to indicate s doesn not exist and the function is one-to-one return [0] * n
def test_run_and_measure(local_qvm_quilc): qc = get_qc("9q-generic-qvm") prog = Program(I(8)) trials = 11 # note to devs: this is included as an example in the run_and_measure docstrings # so if you change it here ... change it there! with local_forest_runtime(): # Redundant with test fixture. bitstrings = qc.run_and_measure(prog, trials) bitstring_array = np.vstack(bitstrings[q] for q in qc.qubits()).T assert bitstring_array.shape == (trials, len(qc.qubits()))
def solve(self): with local_forest_runtime(): qc = get_qc('9q-square-qvm') n_trials = 10 result = qc.run_and_measure(self.__p, trials=self.n_trials) values = list() for j in range(self.n_trials): value = '' for i in range(self.n): value += str(result[i][j]) values.append(value) return values
def grovers_algorithm(f, n): """ This function is intended to determine if there exists an x in {0,1}^n s.t. f(x) = 1 for a given function f s.t. f:{0,1}^n -> {0,1}. The algorithm first constructs Zf, -Z0 gates, initializes with Hanamard matrices, and applies G = -H^n o Z0 o H^n o Zf. This algorithm is not deterministic, so G is applied multiple times. More specifically, G is run (pi / 4 * sqrt(n)) times. Furthermore, there are 10 trials to minimize the chance of a false negative. This function has an anonymous function and integer n as parameters. This function runs the algorithm as described for each 10 trials, and then checks if for any of the outputted states x, if f(x) = 1. If this is true, then 1 is returned, otherwise 0 is returned. The function returns 0 if there is an issue with the simulator. This function uses 9q-squared-qvm, so it assumes that n <= 9 """ # Apply Hadamards to all qubits program = initialize([0] * n) qubits = list(range(n)) # Define and generate Z0 gate (really -Z0) z0_gate = get_Z0(n) Z0 = z0_gate.get_constructor() # Define and generate Zf gate zf_gate = get_Zf(f, n) Zf = zf_gate.get_constructor() # Determine the number of times to apply G iteration_count = floor(pi / 4 * sqrt(n)) h_qubits = [1] * n # Apply G iteration_count times for i in range(iteration_count): # Apply Zf program += zf_gate program += Zf(*qubits) # Apply H to all qubits apply_H(program, h_qubits) # Apply -Z0 program += z0_gate program += Z0(*qubits) # Apply H to all qubits apply_H(program, h_qubits) # Measure # Try to run simulator with local_forest_runtime(): # assumes that n <= 9 qvm = get_qc('9q-square-qvm') # run circuit and measure the qubits, 10 trials results = qvm.run_and_measure(program, trials=10) # Iterate through different results of the different trials and check if f(x) = 1 for i in range(len(results)): new = list() for j in range(len(results[i])): new.append(results[i][j]) if f(new) == 1: return 1 # return 0 if simulator fails return 0
def solve(self): ''' Run and measure the quantum circuit and return the results. ''' with local_forest_runtime(): qc = get_qc('9q-square-qvm') qc.compiler.client.timeout = 10000 result = qc.run_and_measure(self.__p, trials=1) a = '' for i in range(self.n): a += str(result[i][0]) return a
def solve(self): ''' Run and measure the quantum circuit and return the result. The circuit is run for n_trials number of trials. ''' with local_forest_runtime(): qc = get_qc('9q-square-qvm') qc.compiler.client.timeout = 10000 n_trials = 10 result = qc.run_and_measure(self.__p, trials=self.n_trials) values = list() for j in range(self.n_trials): value = '' for i in range(self.n): value += str(result[i][j]) values.append(value) return values
def simulate_pyquil(self, program: Program, title: str, shots=1000): """ qvm -S and quilc -S must be executed to run the pyquil compiler and simulator servers http://docs.rigetti.com/en/stable/start.html """ qubits = program.get_qubits() qubit_size = len(qubits) program.wrap_in_numshots_loop(shots) with local_forest_runtime(): # create a simulator for the given qubit size that is fully sonnected qvm = get_qc(str(qubit_size) + 'q-qvm') # default timeout is not enough for some circuits like shor_general(3) --> https://github.com/rigetti/pyquil/issues/935 qvm.compiler.client.timeout = 60 # print(program) executable = qvm.compile(program) # print(executable.program) bitstrings = qvm.run(executable) counts = self._bitstrings_to_counts(bitstrings) plot_histogram(counts, title=title) return counts
def bernstein_vazirani_algorithm(f, n): """ This function is intended to determine to find a,b s.t. f(x) = a*x + b where a*x is bitwise inner product and + is addition modulo 2, for a given function f s.t. f:{0,1}^n -> {0,1}. It is assumed that f can be represented as f(x) = a*x + b. The algorithm first calculates b by solving for f(0^n). It then initializes the qubits with H for the first n qubits and X and H for the last qubit. The algorithm then constructs a Uf oracle gate based on the function input f. It then applies Uf to all the qubits and applies H to the first n qubits. Finally, the simulator is run on the circuit and measures the results. The function then returns the first n measured qubits. This function has an anonymous function and integer n as parameters. This function uses 9q-squared-qvm, so it assumes that n <= 9. """ initialize_list = [0] * n # calculate b by f(0^n) = b b = f(initialize_list) # Initialize circuit by applying H to first n qubits and X H to last qubit (ancilla qubit) initialize_list.append(1) qubits = list(range(len(initialize_list))) program = initialize(initialize_list) # Generate a Uf oracle gate based on given function f uf_gate = generate_uf(f, n, "Uf") Uf = uf_gate.get_constructor() # Add Uf to circuit program += uf_gate program += Uf(*qubits) # Apply H to all qubits except for the last qubit apply_to_list = [1] * n apply_to_list.append(0) program = apply_H(program, apply_to_list) # print(program) # run simulator and measure qubits with local_forest_runtime(): # Assume n <= 9 qvm = get_qc('9q-square-qvm') # 1 trial because DJ is deterministic results = qvm.run_and_measure(program, trials=1) # retrive measurement of first n qubits a = [] for i in range(n): a.append(results[i][0]) # return a,b return a, b # in case of failure, return b, None return b, None
def deutsch_jozsa_algorithm(f, n): """ This function is intended to determine if f is constant or balanced for a given function f s.t. f:{0,1}^n -> {0,1}. The algorithm initializes the qubits with H for the first n qubits and X and H for the last qubit. The algorithm then constructs a Uf oracle gate based on the function input f. It then applies Uf to all the qubits and applies H to the first n qubits. Finally, the simulator is run on the circuit and measures the results. If upon measurement, the first n qubits are all 0, 1 is returned and the function is constant, otherwise 0 is returned and the function is balanced. This function has an anonymous function and integer n as parameters. This function uses 9q-squared-qvm, so it assumes that n <= 9. """ # apply H to first n qubits and X H to the last qubit (ancilla qubit) initialize_list = [0] * n initialize_list.append(1) qubits = list(range(len(initialize_list))) program = initialize(initialize_list) # Generate Uf oracle from f (anonymous function) uf_gate = generate_uf(f, n, "Uf") Uf = uf_gate.get_constructor() # Add Uf to circuit program += uf_gate program += Uf(*qubits) # Apply Hadamards to first n qubits apply_to_list = [1] * n apply_to_list.append(0) program = apply_H(program, apply_to_list) # print(program) # Run simulator with local_forest_runtime(): # Assume n <= 9 qvm = get_qc('9q-square-qvm') # 1 trial because DJ is deterministic results = qvm.run_and_measure(program, trials=1) # check if first n qubits are all 0 for i in range(n): if (results[i] != 0): return 0 return 1 # in case of failure, return 0 return 0
""" uf_definition = DefGate("UF-GATE", uf_matrix) UF_GATE = uf_definition.get_constructor() return uf_definition, UF_GATE # Define size of algorithm n = 4 uf_definition, UF_GATE = Uf(uf_01) # construct a (0*n, 1) state zeros = [0] * n zeros.append(1) p = init_qubits(zeros) p += uf_definition # apply Hadamards for i in range(len(zeros)): p += H(i) # apply Uf gate p += UF_GATE() # apply final Hadamards for i in range(len(zeros) - 1): p += H(i) with local_forest_runtime(): qvm = get_qc('9q-square-qvm') results = qvm.run_and_measure(p, trials=10) print(results[0]) print(results[1])