def test_simulation_cnot(): """ Test if the simulation of CNOT is accurate :return: """ prog = Program().inst([H(0), CNOT(0, 1)]) qvmstab = QVM_Stabilizer(num_qubits=2) qvmstab._apply_hadamard(prog.instructions[0]) qvmstab._apply_cnot(prog.instructions[1]) # assert that ZZ XX stabilizes a bell state true_stabilizers = [sX(0) * sX(1), sZ(0) * sZ(1)] test_paulis = binary_stabilizer_to_pauli_stabilizer(qvmstab.tableau[2:, :]) for idx, term in enumerate(test_paulis): assert term == true_stabilizers[idx] # test that CNOT does nothing to |00> state prog = Program().inst([CNOT(0, 1)]) qvmstab = QVM_Stabilizer(num_qubits=2) qvmstab._apply_cnot(prog.instructions[0]) true_tableau = np.array([ [1, 1, 0, 0, 0], # X1 -> X1 X2 [0, 1, 0, 0, 0], # X2 -> X2 [0, 0, 1, 0, 0], # Z1 -> Z1 [0, 0, 1, 1, 0] ]) # Z2 -> Z1 Z2 # note that Z1, Z1 Z2 still stabilizees |00> assert np.allclose(true_tableau, qvmstab.tableau) # test that CNOT produces 11 state after X prog = Program().inst([H(0), S(0), S(0), H(0), CNOT(0, 1)]) qvmstab = QVM_Stabilizer(num_qubits=2) qvmstab._apply_hadamard(prog.instructions[0]) qvmstab._apply_phase(prog.instructions[1]) qvmstab._apply_phase(prog.instructions[2]) qvmstab._apply_hadamard(prog.instructions[3]) qvmstab._apply_cnot(prog.instructions[4]) true_tableau = np.array([[1, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 1], [0, 0, 1, 1, 0]]) # note that -Z1, Z1 Z2 still stabilizees |11> assert np.allclose(true_tableau, qvmstab.tableau) test_paulis = binary_stabilizer_to_pauli_stabilizer( qvmstab.stabilizer_tableau()) state = project_stabilized_state(test_paulis, qvmstab.num_qubits, classical_state=[1, 1]) state_2 = project_stabilized_state(test_paulis, qvmstab.num_qubits) assert np.allclose(np.array(state.todense()), np.array(state_2.todense()))
def test_measurement_commuting_result_one(): """ Test measuremt of stabilzier state from tableau This tests when the measurement operator commutes with the stabilizers This time we will generate the stabilizer -Z|1> = |1> so we we need to do a bitflip...not just identity. A Bitflip is HSSH = X """ identity_program = Program().inst([H(0), S(0), S(0), H(0)]).measure(0, 0) qvmstab = QVM_Stabilizer() results = qvmstab.run(identity_program, trials=1000) assert all(np.array(results) == 1)
def test_dagger(): p = Program(X(0), H(0)) assert p.dagger().out() == "DAGGER H 0\nDAGGER X 0\n" p = Program(X(0), MEASURE(0, MemoryReference("ro", 0))) with pytest.raises(ValueError): p.dagger().out() # ensure that modifiers are preserved https://github.com/rigetti/pyquil/pull/914 p = Program() control = 0 target = 1 cnot_control = 2 p += X(target).controlled(control) p += Y(target).controlled(control) p += Z(target).controlled(control) p += H(target).controlled(control) p += S(target).controlled(control) p += T(target).controlled(control) p += PHASE(pi, target).controlled(control) p += CNOT(cnot_control, target).controlled(control) for instr, instr_dagger in zip(reversed(p._instructions), p.dagger()._instructions): assert "DAGGER " + instr.out() == instr_dagger.out()
def expectation(pauli, qubit): """Returns a pyquil.Program with the correct basis measurement for the given Pauli operator and qubit. Args: pauli : str Either "X", "Y", or "Z". qubit : int Index of qubit in the Hamiltonian. Note: This should be an actual physical qubit index on the qubit lattice being considered if running on a quantum chip. """ # Get the index of the classical register for the given qubit index if qubit == 10: ind = 0 elif qubit == 11: ind = 1 elif qubit == 17: ind = 2 else: raise ValueError( "Unsupported qubit index for computer. Rigetti will let you know about this..." ) # Do the appropriate basis measurement if pauli == "Z": return Program(MEASURE(qubit, creg[ind])) elif pauli == "X": return Program(H(qubit), MEASURE(qubit, creg[ind])) elif pauli == "Y": return Program(S(qubit), H(qubit), MEASURE(qubit, creg[ind])) else: raise ValueError("Unsupported operator. Enter X, Y, or Z.")
def _evaluate_single_term(self, ansatz_circuit: Program, meas_term: PauliTerm) -> np.ndarray: """Compute the expectation value of a single PauliTerm , given a quantum circuit to evaluate on. Args: ansatz_circuit: A Program representing the quantum state to evaluate the PauliTerm on. meas_term: a PauliTerm object to be evaluated. """ # First, create the quantum circuit needed for evaluation. # concatenate operator (converted to a Program) and ansatz circuit expectation_circuit = ansatz_circuit.copy() expectation_circuit += meas_term.program ro = expectation_circuit.declare('ro', 'BIT', len(meas_term.get_qubits())) # add necessary post-rotations and measurement for i, qubit in enumerate(sorted(list(meas_term.get_qubits()))): if meas_term.pauli_string([qubit]) == 'X': expectation_circuit += H(qubit) elif meas_term.pauli_string([qubit]) == 'Y': expectation_circuit += H(qubit) expectation_circuit += S(qubit) expectation_circuit += Program().measure(qubit, ro[i]) result = self._run(expectation_circuit, num_shots=self._num_shots_evaluation) return result
def test_dagger(): # these gates are their own inverses p = Program().inst(I(0), X(0), Y(0), Z(0), H(0), CNOT(0, 1), CCNOT(0, 1, 2), SWAP(0, 1), CSWAP(0, 1, 2)) assert p.dagger().out() == 'CSWAP 0 1 2\nSWAP 0 1\n' \ 'CCNOT 0 1 2\nCNOT 0 1\nH 0\n' \ 'Z 0\nY 0\nX 0\nI 0\n' # these gates require negating a parameter p = Program().inst(PHASE(pi, 0), RX(pi, 0), RY(pi, 0), RZ(pi, 0), CPHASE(pi, 0, 1), CPHASE00(pi, 0, 1), CPHASE01(pi, 0, 1), CPHASE10(pi, 0, 1), PSWAP(pi, 0, 1)) assert p.dagger().out() == 'PSWAP(-pi) 0 1\n' \ 'CPHASE10(-pi) 0 1\n' \ 'CPHASE01(-pi) 0 1\n' \ 'CPHASE00(-pi) 0 1\n' \ 'CPHASE(-pi) 0 1\n' \ 'RZ(-pi) 0\n' \ 'RY(-pi) 0\n' \ 'RX(-pi) 0\n' \ 'PHASE(-pi) 0\n' # these gates are special cases p = Program().inst(S(0), T(0), ISWAP(0, 1)) assert p.dagger().out() == 'PSWAP(pi/2) 0 1\n' \ 'RZ(pi/4) 0\n' \ 'PHASE(-pi/2) 0\n' # must invert defined gates G = np.array([[0, 1], [0 + 1j, 0]]) p = Program().defgate("G", G).inst(("G", 0)) assert p.dagger().out() == 'DEFGATE G-INV:\n' \ ' 0.0, -i\n' \ ' 1.0, 0.0\n\n' \ 'G-INV 0\n' # can also pass in a list of inverses inv_dict = {"G": "J"} p = Program().defgate("G", G).inst(("G", 0)) assert p.dagger(inv_dict=inv_dict).out() == 'J 0\n' # defined parameterized gates cannot auto generate daggered version https://github.com/rigetticomputing/pyquil/issues/304 theta = Parameter('theta') gparam_matrix = np.array([[quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [-1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) g_param_def = DefGate('GPARAM', gparam_matrix, [theta]) p = Program(g_param_def) with pytest.raises(TypeError): p.dagger() # defined parameterized gates should passback parameters https://github.com/rigetticomputing/pyquil/issues/304 GPARAM = g_param_def.get_constructor() p = Program(GPARAM(pi)(1, 2)) assert p.dagger().out() == 'GPARAM-INV(pi) 1 2\n'
def prepare_measurement(qubit, direction, program): if direction == 'x': program += H(qubit) else: program += H(qubit) program_S_dagger = Program() program_S_dagger += S(qubit) program += program_S_dagger.dagger() return program
def test_simulation_phase(): """ Test if the Phase gate is applied correctly to the tableau S|0> = |0> S|+> = |R> """ prog = Program().inst(S(0)) qvmstab = QVM_Stabilizer(num_qubits=1) qvmstab._apply_phase(prog.instructions[0]) true_stab = np.array([[1, 1, 0], [0, 1, 0]]) assert np.allclose(true_stab, qvmstab.tableau) prog = Program().inst([H(0), S(0)]) qvmstab = QVM_Stabilizer(num_qubits=1) qvmstab._apply_hadamard(prog.instructions[0]) qvmstab._apply_phase(prog.instructions[1]) true_stab = np.array([[0, 1, 0], [1, 1, 0]]) assert np.allclose(true_stab, qvmstab.tableau)
def test_dagger(): # these gates are their own inverses p = Program().inst(I(0), X(0), Y(0), Z(0), H(0), CNOT(0,1), CCNOT(0,1,2), SWAP(0,1), CSWAP(0,1,2)) assert p.dagger().out() == 'CSWAP 0 1 2\nSWAP 0 1\n' \ 'CCNOT 0 1 2\nCNOT 0 1\nH 0\n' \ 'Z 0\nY 0\nX 0\nI 0\n' # these gates require negating a parameter p = Program().inst(PHASE(pi, 0), RX(pi, 0), RY(pi, 0), RZ(pi, 0), CPHASE(pi, 0, 1), CPHASE00(pi, 0, 1), CPHASE01(pi, 0, 1), CPHASE10(pi, 0, 1), PSWAP(pi, 0, 1)) assert p.dagger().out() == 'PSWAP(-3.141592653589793) 0 1\n' \ 'CPHASE10(-3.141592653589793) 0 1\n' \ 'CPHASE01(-3.141592653589793) 0 1\n' \ 'CPHASE00(-3.141592653589793) 0 1\n' \ 'CPHASE(-3.141592653589793) 0 1\n' \ 'RZ(-3.141592653589793) 0\n' \ 'RY(-3.141592653589793) 0\n' \ 'RX(-3.141592653589793) 0\n' \ 'PHASE(-3.141592653589793) 0\n' # these gates are special cases p = Program().inst(S(0), T(0), ISWAP(0, 1)) assert p.dagger().out() == 'PSWAP(1.5707963267948966) 0 1\n' \ 'RZ(0.7853981633974483) 0\n' \ 'PHASE(-1.5707963267948966) 0\n' # must invert defined gates G = np.array([[0, 1], [0+1j, 0]]) p = Program().defgate("G", G).inst(("G", 0)) assert p.dagger().out() == 'DEFGATE G-INV:\n' \ ' 0.0+-0.0i, 0.0-1.0i\n' \ ' 1.0+-0.0i, 0.0+-0.0i\n\n' \ 'G-INV 0\n' # can also pass in a list of inverses inv_dict = {"G":"J"} p = Program().defgate("G", G).inst(("G", 0)) assert p.dagger(inv_dict=inv_dict).out() == 'J 0\n'
def get_test_program(measure: bool = False) -> Program: PI = float(pi.evalf()) p = Program() p += X(0) p += Y(1) p += Z(2) p += H(3) p += S(0) p += T(1) p += RX(PI / 2, 2) p += RY(PI / 2, 3) p += RZ(PI / 2, 0) p += CZ(0, 1) p += CNOT(2, 3) p += CCNOT(0, 1, 2) p += CPHASE(PI / 4, 2, 1) p += SWAP(0, 3) if measure: ro = p.declare("ro", "BIT", 4) p += MEASURE(0, ro[0]) p += MEASURE(3, ro[1]) p += MEASURE(2, ro[2]) p += MEASURE(1, ro[3]) return p
def test_singles(): p = Program(I(0), X(0), Y(1), Z(1), H(2), T(2), S(1)) assert p.out() == "I 0\nX 0\nY 1\nZ 1\nH 2\nT 2\nS 1\n"
# # job = execute(circ, backend, shots=10) # result = job.result() # counts = result.get_counts(circ) # # print(counts) ## personal testing # theoretical_probs = {'00000': 0.10139983459411607, '00001': 0.01735805702132643, '00010': 0.017358057021326437, '00011': 0.043801529890753046, '00100': 0.017358057021326423, '00101': 0.043801529890753046, '00110': 0.043801529890753046, '00111': 0.0017330570213264689, '01000': 0.017358057021326437, '01001': 0.04380152989075303, '01010': 0.043801529890753046, '01011': 0.0017330570213264678, '01100': 0.04380152989075303, '01101': 0.0017330570213264689, '01110': 0.0017330570213264678, '01111': 0.05942652989075301, '10000': 0.017358057021326437, '10001': 0.04380152989075307, '10010': 0.04380152989075308, '10011': 0.0017330570213264678, '10100': 0.04380152989075307, '10101': 0.0017330570213264689, '10110': 0.0017330570213264678, '10111': 0.05942652989075301, '11000': 0.04380152989075308, '11001': 0.0017330570213264695, '11010': 0.0017330570213264695, '11011': 0.05942652989075301, '11100': 0.0017330570213264654, '11101': 0.05942652989075301, '11110': 0.05942652989075301, '11111': 0.05933136172468943} # experimental_probs = {'00000': 0.0997, '00001': 0.0175, '00010': 0.015, '00011': 0.0418, '00100': 0.017, '00101': 0.0459, '00110': 0.0443, '00111': 0.0018, '01000': 0.0155, '01001': 0.0471, '01010': 0.0451, '01011': 0.0015, '01100': 0.039, '01101': 0.0018, '01110': 0.0014, '01111': 0.0611, '10000': 0.0201, '10001': 0.0449, '10010': 0.043, '10011': 0.0021, '10100': 0.0446, '10101': 0.0023, '10110': 0.0022, '10111': 0.0582, '11000': 0.0435, '11001': 0.0018, '11010': 0.0016, '11011': 0.0595, '11100': 0.0024, '11101': 0.0631, '11110': 0.0612, '11111': 0.054} # # # for key in theoretical_probs.keys(): # if key in experimental_probs.keys(): # print("present") # else: # print("not present") from pyquil.quil import Gate from pyquil.gates import H, CNOT, S from pyquil import Program, get_qc from pyquil.latex import to_latex from pyquil.api import local_qvm qvm = get_qc('3q-qvm') program = Program(H(2)) program += S(2) program += Gate.dagger(S(2)) print(to_latex(program))
def test_S(): u1 = program_unitary(Program(S(0)), n_qubits=1) u2 = program_unitary(_S(0), n_qubits=1) assert equal_up_to_global_phase(u1, u2, atol=1e-12)