def get_hhl_2x2(A, b, r, qubits): '''Generate a circuit that implements the full HHL algorithm for the case of 2x2 matrices. :param A: (numpy.ndarray) A Hermitian 2x2 matrix. :param b: (numpy.ndarray) A vector. :param r: (float) Parameter to be tuned in the algorithm. :param verbose: (bool) Optional information about the wavefunction. :return: A Quil program to perform HHL. ''' p = pq.Program() p.inst(create_arbitrary_state(b, [qubits[3]])) p.inst(H(qubits[1])) p.inst(H(qubits[2])) p.defgate('CONTROLLED-U0', controlled(scipy.linalg.expm(2j*π*A/4))) p.inst(('CONTROLLED-U0', qubits[2], qubits[3])) p.defgate('CONTROLLED-U1', controlled(scipy.linalg.expm(2j*π*A/2))) p.inst(('CONTROLLED-U1', qubits[1], qubits[3])) p.inst(SWAP(qubits[1], qubits[2])) p.inst(H(qubits[2])) p.defgate('CSdag', controlled(np.array([[1, 0], [0, -1j]]))) p.inst(('CSdag', qubits[1], qubits[2])) p.inst(H(qubits[1])) p.inst(SWAP(qubits[1], qubits[2])) uncomputation = p.dagger() p.defgate('CRy0', controlled(rY(2*π/2**r))) p.inst(('CRy0', qubits[1], qubits[0])) p.defgate('CRy1', controlled(rY(π/2**r))) p.inst(('CRy1', qubits[2], qubits[0])) p += uncomputation return p
def create_initial_state_program(self, initial_state): """ Creates a pyquil program representing the initial state for the QAOA. As an argument it takes either a list with order of the cities, or a string "all". In the second case the initial state is superposition of all possible states for this problem. """ initial_state_program = pq.Program() if type(initial_state) is list: for i in range(self.reduced_number_of_nodes): initial_state_program.inst(X(i * (self.reduced_number_of_nodes) + initial_state[i])) elif initial_state == "all": vector_of_states = np.zeros(2**self.number_of_qubits) list_of_possible_states = [] initial_order = range(0, self.reduced_number_of_nodes) all_permutations = [list(x) for x in itertools.permutations(initial_order)] for permutation in all_permutations: coding_of_permutation = 0 for i in range(len(permutation)): coding_of_permutation += 2**(i * (self.reduced_number_of_nodes) + permutation[i]) vector_of_states[coding_of_permutation] = 1 initial_state_program = create_arbitrary_state(vector_of_states) return initial_state_program
def create_initial_state_program(self): """ As an initial state I use state, where in t=i we visit i-th city. """ initial_state = pq.Program() number_of_nodes = len(self.nodes_array) if type(self.initial_state) is list: for i in range(number_of_nodes): initial_state.inst( X(i * number_of_nodes + self.initial_state[i])) elif self.initial_state == "all": vector_of_states = np.zeros(2**self.number_of_qubits) list_of_possible_states = [] initial_order = range(0, number_of_nodes) all_permutations = [ list(x) for x in itertools.permutations(initial_order) ] for permutation in all_permutations: coding_of_permutation = 0 for i in range(len(permutation)): coding_of_permutation += 2**(i * number_of_nodes + permutation[i]) vector_of_states[coding_of_permutation] = 1 initial_state = create_arbitrary_state(vector_of_states) return initial_state
def wrap(theta): """ Creates arbitrary state using stereographic projection. :param theta: Vector representing the state. :return: PyQuil program setting up the state. """ return create_arbitrary_state(maps.plane_to_sphere(theta, pole))
def wrap(theta: np.ndarray): """ Creates arbitrary state. :param theta: Vector representing the state. :return: PyQuil program setting up the state. """ theta = np.concatenate((np.array([1]) / np.sqrt(dim), theta), axis=0) return create_arbitrary_state(theta)
def wrap(theta: np.ndarray) -> Program: """ Creates arbitrary one-particle state. :param theta: Coefficients in superposition. :return: Pyquil program setting up the state. """ vector = np.zeros(2**dim) vector[1] = 1 / np.sqrt(dim) vector[[2**(i + 1) for i in range(dim - 1)]] = theta vector *= 1 / np.linalg.norm(vector) return create_arbitrary_state(vector)
def create_initial_state_program(): initial_state_program = pq.Program() vector_of_states = np.zeros(2**number_of_qubits) list_of_possible_states = [] initial_order = range(0, reduced_number_of_nodes) all_permutations = [list(x) for x in itertools.permutations(initial_order)] for permutation in all_permutations: coding_of_permutation = 0 for i in range(len(permutation)): coding_of_permutation += 2**(i * (reduced_number_of_nodes) + permutation[i]) vector_of_states[coding_of_permutation] = 1 initial_state_program = create_arbitrary_state(vector_of_states) return initial_state_program
def verify_with_swap_test_2x2(reference_amplitudes, qubits): '''Generate a circuit for performing a swap test. :param program: (pyquil.quil.Program) Program storing the HHL algorithm. :param reference_amplitudes: (numpy.ndarray) Amplitudes of the state to be compared against. :return: A Quil program to do a swap test after inverting 2x2 matrices. ''' swaptest = pq.Program() swaptest.inst(create_arbitrary_state(reference_amplitudes, [qubits[4]])) swaptest.inst(H(qubits[5])) swaptest.inst(CSWAP(qubits[5], qubits[4], qubits[3])) swaptest.inst(H(qubits[5])) c = swaptest.declare('ro', 'BIT', 2) swaptest += MEASURE(qubits[0], c[0]) # This is actually the post-selection in HHL swaptest += MEASURE(qubits[5], c[1]) return swaptest
def get_hhl_2x2_corrected(A, b, r, qubits): """ HHL program with bit code corrections on first two H gates """ p = pq.Program() p.inst(create_arbitrary_state(b, [qubits[3]])) # PHASE ESTIMATION bit_code_H(p, qubits[1], qubits) bit_code_H(p, qubits[2], qubits) p.defgate('CONTROLLED-U0', controlled(scipy.linalg.expm(2j*π*A/4))) p.inst(('CONTROLLED-U0', qubits[2], qubits[3])) p.defgate('CONTROLLED-U1', controlled(scipy.linalg.expm(2j*π*A/2))) p.inst(('CONTROLLED-U1', qubits[1], qubits[3])) p.inst(SWAP(qubits[1], qubits[2])) p.inst(H(qubits[2])) p.defgate('CSdag', controlled(np.array([[1, 0], [0, -1j]]))) p.inst(('CSdag', qubits[1], qubits[2])) p.inst(H(qubits[1])) p.inst(SWAP(qubits[1], qubits[2])) p.defgate('CRy0', controlled(rY(2*π/2**r))) p.inst(('CRy0', qubits[1], qubits[0])) p.defgate('CRy1', controlled(rY(π/2**r))) p.inst(('CRy1', qubits[2], qubits[0])) # HARD CODE THE INVERSE PHASE ESTIMATION :'( p.inst(SWAP(qubits[1], qubits[2])) p.inst(H(qubits[1])) p.defgate('CSdag-INV', controlled(np.array([[1, 0], [0, 1j]]))) p.inst(('CSdag-INV', qubits[1], qubits[2])) p.inst(H(qubits[2])) p.inst(SWAP(qubits[1], qubits[2])) p.defgate('CONTROLLED-U1-INV', controlled(scipy.linalg.expm(-2j*π*A/2))) p.inst(('CONTROLLED-U1-INV', qubits[1], qubits[3])) p.defgate('CONTROLLED-U0-INV', controlled(scipy.linalg.expm(-2j*π*A/4))) p.inst(('CONTROLLED-U0-INV', qubits[2], qubits[3])) p.inst(H(qubits[2])) p.inst(H(qubits[1])) # undoes create_arbitrary_state p.inst(RY(π/2, qubits[3])) p.inst(H(qubits[3])) return p
# We need to do this inc ase registers are entangled. hhl += uncomputation # Rejection sampling on the acnilla register and a swap test # The state |x> = A^-1 |b> is prop to sum_J beta_j lambda_j^-1 |u_j> # contains info about the solution to Ax = b when measuring 1 on the ancilla state. # We perform post selection by projecting onto the desired |1> # To check the solution is the expected one, we prepare the correct output state # manually to perform a swap test with the outcome. from grove.alpha.arbitrary_state.arbitrary_state import create_arbitrary_state reference_amplitudes = [0.9492929682, 0.3143928443] # Target state prep hhl += create_arbitrary_state(reference_amplitudes, [4]) # Swap test hhl += H(5) hhl += CSWAP(5, 4, 3) hhl += H(5) c = hhl.declare('ro', 'BIT', 2) hhl += MEASURE(0, c[0]) hhl += MEASURE(5, c[1]) # it is a good ex to check if the right result is given by the state # |x> = 0.949 |0> + 0.314 |1> # There are tow measuresments performed, one of the ancilla register ( for doing post selection) # and another one that gives the result of the swap test. To calculate success probabilities, define helper functions