def test_exponentiate_identity(): generator = PauliTerm("I", 1, 0.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst([X(0), PHASE(0)(0), X(0), PHASE(0)(0)]) compare_progs(prog, result_prog) generator = PauliTerm("I", 1, 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst([X(0), PHASE(-1.0)(0), X(0), PHASE(-1.0)(0)]) compare_progs(prog, result_prog) generator = PauliTerm("I", 10, 0.08) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst( [X(0), PHASE(-0.08)(0), X(0), PHASE(-0.08)(0)]) compare_progs(prog, result_prog)
def test_larger_qaoa_circuit(): square_qaoa_circuit = [ H(0), H(1), H(2), H(3), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(0, 1), RZ(0.78564882604980579, 1), CNOT(0, 1), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(0, 3), RZ(0.78564882604980579, 3), CNOT(0, 3), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(1, 2), RZ(0.78564882604980579, 2), CNOT(1, 2), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(2, 3), RZ(0.78564882604980579, 3), CNOT(2, 3), H(0), RZ(-0.77868204192240842, 0), H(0), H(1), RZ(-0.77868204192240842, 1), H(1), H(2), RZ(-0.77868204192240842, 2), H(2), H(3), RZ(-0.77868204192240842, 3), H(3), ] prog = Program(square_qaoa_circuit) qam = PyQVM(n_qubits=4, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) wf = qam.wf_simulator.wf wf_true = np.array( [ 8.43771693e-05 - 0.1233845 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -4.99915497e-01 - 0.12363516 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -4.99915497e-01 - 0.12363516 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, 8.43771693e-05 - 0.1233845 * 1j, ] ) np.testing.assert_allclose(wf_true, wf)
0.0625 + 0.0j, 0.0625 + 0.0j, 0.0625 + 0.0j, 0.0625 + 0.0j, 0.0625 + 0.0j, 0.0625 + 0.0j, 0.0625 + 0.0j, 0.0625 + 0.0j, ] HADAMARD_WF = [0.70710678 + 0.0j, 0.70710678 + 0.0j] ARBITRARY_STATE_GEN_INSTRUCTIONS = { 1: [ RZ(-1.3778211380875056, 0), PHASE(1.3778211380875056, 0), H(0), RY(-1.5707963267948963, 0), RZ(-1.3778211380875056, 0), ], 2: [ RZ(3.9156492624160952, 0), PHASE(-3.9156492624160952, 0), H(0), RY(-1.334414217642601, 0), RZ(-0.51915346851116273, 0), ], 3: [ RZ(1.1065191340906928, 0), PHASE(-1.1065191340906928, 0), H(0),
def test_phases(): p = Program(PHASE(np.pi, 1), CPHASE00(np.pi, 0, 1), CPHASE01(np.pi, 0, 1), CPHASE10(np.pi, 0, 1), CPHASE(np.pi, 0, 1)) assert p.out() == 'PHASE(pi) 1\nCPHASE00(pi) 0 1\n' \ 'CPHASE01(pi) 0 1\nCPHASE10(pi) 0 1\n' \ 'CPHASE(pi) 0 1\n'
def test_rb_sequence(server, mock_rb_cxn): response = mock_rb_cxn.generate_rb_sequence(2, [PHASE(np.pi / 2, 0), H(0)]) assert [prog.out() for prog in response] == [prog.out() for prog in RB_REPLY]
from pyquil.quil import Program from pyquil.api import QVMConnection from pyquil.gates import H, PHASE from pyquilcompiler import compiletoquil import numpy as np # Invoking and renaming qvm = QVMConnection() p = Program() # Gate implementation p.inst(H(0)) theta = np.pi / 2 p.inst(PHASE(theta, 0)) # Measurement p.measure(0, 0) p.measure(1, 1) # Running the program compiletoquil(p) cr = [] results = qvm.run(p, cr, 4) print(results)
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/rigetti/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/rigetti/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' # 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) assert p.dagger().out() == 'CONTROLLED CNOT 0 2 1\n' \ 'CONTROLLED PHASE(-pi) 0 1\n' \ 'CONTROLLED RZ(pi/4) 0 1\n' \ 'CONTROLLED PHASE(-pi/2) 0 1\n' \ 'CONTROLLED H 0 1\n' \ 'CONTROLLED Z 0 1\n' \ 'CONTROLLED Y 0 1\n' \ 'CONTROLLED X 0 1\n'
def test_local_rb_sequence(benchmarker): response = benchmarker.generate_rb_sequence( 2, [PHASE(np.pi / 2, 0), H(0)], seed=52) assert [prog.out() for prog in response] == \ ["H 0\nPHASE(pi/2) 0\nH 0\nPHASE(pi/2) 0\nPHASE(pi/2) 0\n", "H 0\nPHASE(pi/2) 0\nH 0\nPHASE(pi/2) 0\nPHASE(pi/2) 0\n"]
def test_larger_qaoa_density(): prog = Program( H(0), H(1), H(2), H(3), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(0, 1), RZ(0.78564882604980579, 1), CNOT(0, 1), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(0, 3), RZ(0.78564882604980579, 3), CNOT(0, 3), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(1, 2), RZ(0.78564882604980579, 2), CNOT(1, 2), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(2, 3), RZ(0.78564882604980579, 3), CNOT(2, 3), H(0), RZ(-0.77868204192240842, 0), H(0), H(1), RZ(-0.77868204192240842, 1), H(1), H(2), RZ(-0.77868204192240842, 2), H(2), H(3), RZ(-0.77868204192240842, 3), H(3), ) qam = PyQVM(n_qubits=4, quantum_simulator_type=ReferenceDensitySimulator).execute(prog) rho_test = qam.wf_simulator.density wf_true = np.array([ 8.43771693e-05 - 0.1233845 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -4.99915497e-01 - 0.12363516 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -4.99915497e-01 - 0.12363516 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, 8.43771693e-05 - 0.1233845 * 1j, ]) wf_true = np.reshape(wf_true, (2**4, 1)) rho_true = np.dot(wf_true, np.conj(wf_true).T) np.testing.assert_allclose(rho_true, rho_test, atol=1e-8)
def main(): qvm = QVMConnection() agave = get_devices(as_dict=True)['8Q-Agave'] qvm_noisy = QVMConnection(agave) print( "Timestamp, Singlet (Wavefunction), Triplet (Wavefunction), Singlet (QVM), Triplet (QVM)," "Singlet (Noise), Triplet (Noise), 00 (Noise), 11 (Noise)," "Singlet (Compiled on QVM), Triplet (Compiled on QVM), 00 (Compiled on QVM), 11 (Compiled on QVM)," ) # Truncate file with compiled code open(FILENAME, "w").close() # Rotation for t in range(0, 50): # ns p = create_singlet_state() add_switch_to_singlet_triplet_basis_gate_to_program(p) w_larmor = 0.46 # 4.6e8 1/s as determined in the experiment p.inst(PHASE(w_larmor * t, 0)) p.inst(("SWITCH_TO_SINGLET_TRIPLET_BASIS", 0, 1)) wavefunction = qvm.wavefunction(p) probs = wavefunction.get_outcome_probs() p.measure(0, 0) p.measure(1, 1) # Run on a perfect QVM (no noise) data = qvm.run(p, trials=1000) # simulate physical noise on QVM data_noisy = qvm_noisy.run(p, trials=1000) noisy_data_distr = distribution(data_noisy) agave = get_devices(as_dict=True)['8Q-Agave'] compiler = CompilerConnection(agave) job_id = compiler.compile_async(p) # wait_for_job has print statement # using this workaround to suppress it import sys, os _old_stdout = sys.stdout with open(os.devnull, 'w') as fp: sys.stdout = fp job = compiler.wait_for_job( job_id) # This is the only line that matters sys.stdout = _old_stdout # Run code compiled for 8Q-Agave on a noisy QVM # Per example on https://github.com/rigetticomputing/pyquil/blob/master/examples/run_quil.py p_compiled = Program(job.compiled_quil()) with open(FILENAME, "a") as fp: fp.write("Timestep: %s\n" % t) fp.write("%s" % job.compiled_quil()) fp.write("\n") data_compiled = qvm_noisy.run(p_compiled, trials=1000) compiled_data_distr = distribution(data_compiled) print("%s, %s, %s, %s, %s, %s, %s, %s ,%s, %s, %s, %s, %s" % ( t, probs['01'], probs['10'], distribution(data).get((0, 1), 0), distribution(data).get((1, 0), 0), noisy_data_distr.get((0, 1), 0), noisy_data_distr.get((1, 0), 0), noisy_data_distr.get((0, 0), 0), noisy_data_distr.get((1, 1), 0), compiled_data_distr.get((0, 1), 0), compiled_data_distr.get((1, 0), 0), compiled_data_distr.get((0, 0), 0), compiled_data_distr.get((1, 1), 0), ))
def __init__(self, N): self.N = N # + 1 to prevent overflow in addition self.n = len([1 if digit == '1' else 0 for digit in bin(N)[2:]]) self.add_ancilla = QubitPlaceholder() self.add_gate = lambda k: (lambda q: PHASE(math.pi / (2**(k - 1)), q))
def controlGate(c, t, Q): """ Returns program that applies a single-qubit control gate to a target qubit. An arbitrary gate is specified, in the style of Rieffel and Polak, by four rotation angles: alpha, beta, delta, gamma. These real numbers uniquely specify a single qubit tranformation, and are stored in a dictionary `Q`. They are indexed by the names above. The control qubit `c` controls the application of the transformation, and the target qubit `t` is what the transformation is applied to. See Rieffel and Polak pgs. 86-87 for an explanation of this algorithm. Parameters ---------- c: list Holds the location of the control qubit. This is a single qubit, so the list must be length-1. t: list Holds the location of the target qubit. This is a single qubit, so the list must be length-1. Additionall, it must be a different qubit from the control qubit. Q: dictionary Holds the four real numbers (angles) necessary to specify an arbitrary single-qubit transformation. Indexed by the names of the angles, namely: alpha, beta, delta, gamma. Returns ------- p: pyQuil Program Set of instructions which carries out a single-qubit control gate transformation. """ if len(c) is not 1: raise Exception("control qubit list must be length-1") if len(t) is not 1: raise Exception("target qubit list must be length-1") if t[0] is c[0]: raise Exception("target and control qubits must be different") if 'alpha' in Q: alpha = Q['alpha'] else: alpha = 0 if 'beta' in Q: beta = Q['beta'] else: beta = 0 if 'delta' in Q: delta = Q['delta'] else: delta = 0 if 'gamma' in Q: gamma = Q['gamma'] else: gamma = 0 p = Program() p.inst(RZ(alpha - gamma, t[0]), CNOT(c[0], t[0])) p.inst(RZ(alpha + gamma, t[0]), RY(beta, t[0]), CNOT(c[0], t[0])) p.inst(RY(-beta, t[0]), RZ(-2 * alpha, t[0])) p.inst(RZ(delta, c[0]), RZ(-delta, c[0]), PHASE(delta, c[0])) return p
def StateInit(qc, circuit_params, p, q, r, s, circuit_choice, control, sign): '''This function computes the state produced after the given circuit, either QAOA, IQP, or IQPy, depending on the value of circuit_choice.''' #sign = 'POSITIVE' for the positive probability version, sign = 'NEGATIVE' for the negative version of the probability (only used to compute the gradients) #final_layer is either 'IQP', 'QAOA', 'IQPy' for IQP (Final Hadamard), QAOA (Final X rotation) or IQPy (Final Y rotation) #control = 'BIAS' for updating biases, = 'WEIGHTS' for updating weights, = 'NEITHER' for neither #Initialise empty quantum program, with QuantumComputer Object, and Wavefunction Simulator '''With Active qubit reset''' # prog = Program(RESET()) '''Without Active qubit reset''' prog = Program() qubits = qc.qubits() N_qubits = len(qubits) #Unpack circuit parameters from dictionary J = circuit_params['J'] b = circuit_params['b'] gamma = circuit_params['gamma'] delta = circuit_params['delta'] #Apply hadarmard to all qubits in computation prog = HadamardToAll(prog, qubits) # print(qc.name) #Apply Control-Phase(4J) gates to each qubit, the factor of 4 comes from the decomposition of the Ising gate #with local Z corrections to neighbouring qubits, coming from the decomposition of the Ising gate #If weight J_{p,q} is updated, add a +/- pi/2 rotation if qc.name.lower() == 'aspen-3-3q-b-qvm': ''''Specific entanglement structure for Rigetti Aspen-3-2Q-C''' if (control.lower() == 'weights' and p == 0 and q == 1): #first weight parameter between qubit[1] and qubit[2] prog.inst( CPHASE(4 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0], qubits[1])) prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0])) prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[1])) elif (control.lower() == 'weights' and p == 1 and q == 2): #Second weight parameter between qubit[1] and qubit[2] prog.inst( CPHASE(4 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[1], qubits[2])) prog.inst(PHASE(-2 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[1])) prog.inst(PHASE(-2 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[2])) elif (control.lower() == 'neither' or 'bias' or 'gamma' and sign.lower() == 'neither'): prog.inst(CPHASE(4 * J[0, 1], qubits[0], qubits[1])) prog.inst(PHASE(-2 * J[0, 1], qubits[0])) prog.inst(PHASE(-2 * J[0, 1], qubits[1])) prog.inst(CPHASE(4 * J[1, 2], qubits[1], qubits[2])) prog.inst(PHASE(-2 * J[1, 2], qubits[1])) prog.inst(PHASE(-2 * J[1, 2], qubits[2])) elif qc.name.lower() == 'aspen-4-3q-a' or qc.name.lower( ) == 'aspen-4-3q-a-qvm': ''''Specific entanglement structure for Rigetti Aspen-4-3Q-A 17 - 10 - 11 ''' if (control.lower() == 'weights' and p == 0 and q == 1): #first weight parameter between qubit[1] and qubit[2] prog.inst( CPHASE(4 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0], qubits[1])) prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0])) prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[1])) elif (control.lower() == 'weights' and p == 1 and q == 2): #Second weight parameter between qubit[1] and qubit[2] prog.inst( CPHASE(4 * J[0, 2] + (-1)**(sign) * pi / 2, qubits[0], qubits[2])) prog.inst(PHASE(-2 * J[0, 2] + (-1)**(sign) * pi / 2, qubits[0])) prog.inst(PHASE(-2 * J[0, 2] + (-1)**(sign) * pi / 2, qubits[2])) elif (control.lower() == 'neither' or 'bias' or 'gamma' and sign.lower() == 'neither'): prog.inst(CPHASE(4 * J[0, 1], qubits[0], qubits[1])) prog.inst(PHASE(-2 * J[0, 1], qubits[0])) prog.inst(PHASE(-2 * J[0, 1], qubits[1])) prog.inst(CPHASE(4 * J[0, 2], qubits[0], qubits[2])) prog.inst(PHASE(-2 * J[0, 2], qubits[0])) prog.inst(PHASE(-2 * J[0, 2], qubits[2])) elif qc.name.lower() == 'aspen-4-4q-a' or qc.name.lower( ) == 'aspen-4-4q-a-qvm': '''' Specific entanglement structure for Rigetti Aspen-4-4Q-A 7 - 0 - 1 - 2 ''' if (control.lower() == 'weights' and p == 0 and q == 1): #first weight parameter between qubit[1] and qubit[2] prog.inst( CPHASE(4 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0], qubits[1])) prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0])) prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[1])) elif (control.lower() == 'weights' and p == 1 and q == 2): #Second weight parameter between qubit[1] and qubit[2] prog.inst( CPHASE(4 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[1], qubits[2])) prog.inst(PHASE(-2 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[1])) prog.inst(PHASE(-2 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[2])) elif (control.lower() == 'weights' and p == 0 and q == 3): #Second weight parameter between qubit[1] and qubit[2] prog.inst( CPHASE(4 * J[0, 3] + (-1)**(sign) * pi / 2, qubits[0], qubits[3])) prog.inst(PHASE(-2 * J[0, 3] + (-1)**(sign) * pi / 2, qubits[0])) prog.inst(PHASE(-2 * J[0, 3] + (-1)**(sign) * pi / 2, qubits[3])) elif (control.lower() == 'neither' or 'bias' or 'gamma' and sign.lower() == 'neither'): prog.inst(CPHASE(4 * J[0, 1], qubits[0], qubits[1])) prog.inst(PHASE(-2 * J[0, 1], qubits[0])) prog.inst(PHASE(-2 * J[0, 1], qubits[1])) prog.inst(CPHASE(4 * J[1, 2], qubits[1], qubits[2])) prog.inst(PHASE(-2 * J[1, 2], qubits[1])) prog.inst(PHASE(-2 * J[1, 2], qubits[2])) prog.inst(CPHASE(4 * J[0, 3], qubits[0], qubits[3])) prog.inst(PHASE(-2 * J[0, 3], qubits[0])) prog.inst(PHASE(-2 * J[0, 3], qubits[3])) else: for j in range(0, N_qubits): for i in range(0, N_qubits): if ( i < j ): #connection is symmetric, so don't overcount entangling gates if (control.lower() == 'weights' and i == p and j == q): prog.inst( CPHASE(4 * J[i, j] + (-1)**(sign) * pi / 2, qubits[i], qubits[j])) prog.inst( PHASE(-2 * J[i, j] + (-1)**(sign) * pi / 2, qubits[i])) prog.inst( PHASE(-2 * J[i, j] + (-1)**(sign) * pi / 2, qubits[j])) elif (control.lower() == 'neither' or 'bias' or 'gamma' and sign.lower() == 'neither'): prog.inst(CPHASE(4 * J[i, j], qubits[i], qubits[j])) prog.inst(PHASE(-2 * J[i, j], qubits[i])) prog.inst(PHASE(-2 * J[i, j], qubits[j])) #Apply local Z rotations (b) to each qubit (with one phase changed by pi/2 if the corresponding parameter {r} is being updated for j in range(0, N_qubits): if (control == 'BIAS' and j == r): prog.inst(PHASE(-2 * b[j] + (-1)**(sign) * pi / 2, qubits[j])) elif (control == 'NEITHER' or 'WEIGHTS' or 'GAMMA' and sign == 'NEITHER'): prog.inst(PHASE(-2 * b[j], qubits[j])) #Apply final 'measurement' layer to all qubits, either all Hadamard, or X or Y rotations if (circuit_choice == 'IQP'): prog = HadamardToAll( prog, qubits ) #If the final 'measurement' layer is to be an IQP measurement (i.e. Hadamard on all qubits) elif (circuit_choice == 'QAOA'): #If the final 'measurement' layer is to be a QAOA measurement (i.e. e^(-i(pi/4)X_i)on all qubits) for k in range(0, N_qubits): # if (control == 'GAMMA' and k == s): # prog.inst(pl.exponential_map(sX(k))(-float(gamma[k])+ (-1)**(sign)*pi/2)) # elif (control == 'NEITHER' or 'WEIGHTS' or 'BIAS' and sign == 'NEITHER'): H_temp = (-float(gamma[k])) * pl.sX(qubits[k]) prog.inst(pl.exponential_map(H_temp)(1.0)) # print('GAMMA IS:',-float(gamma[k])) elif (circuit_choice == 'IQPy'): #If the final 'measurement' layer is to be a IQPy measurement (i.e. e^(-i(pi/4)Y_i) on all qubits) for k in qubits: H_temp = (-float(delta[k])) * pl.sY(qubits[k]) prog.inst(pl.exponential_map(H_temp)(1.0)) else: raise ValueError("circuit_choice must be either \ \'IQP\' for IQP (Final Hadamard), \ \'QAOA\' for QAOA (Final X rotation) or \ \'IQPy\' IQPy (Final Y rotation)") # print(prog) '''Insert explicit measure instruction if required''' # ro = prog.declare('ro', 'BIT', len(qubits)) # prog.inst([MEASURE(qubit, ro[idx]) for idx, qubit in enumerate(qubits)]) return prog
def main(): agave = get_devices(as_dict=True)['8Q-Agave'] compiler = CompilerConnection(agave) qvm = QVMConnection() # Perfect QVM qvm_noisy = QVMConnection(agave) # Simulate Noise qpu = QPUConnection(agave) # Physical QPU print("Timestamp," "Singlet (Wavefunction), Triplet (Wavefunction), " "Singlet (QVM), Triplet (QVM)," "Singlet Mean (QVM Noise), Singlet Std (QVM Noise), " "Triplet Mean (QVM Noise), Triplet Std (QVM Noise)," "00 Mean (QVM Noise), 00 Std (QVM Noise)," "11 Mean (QVM Noise), 11 Std (QVM Noise)," "Singlet Mean (QPU), Singlet Std (QPU)," "Triplet Mean (QPU), Triplet Std (QPU)," "00 Mean (QPU), 00 Std (QPU)," "11 Mean (QPU), 1 Std (QPU)") # Rotation fp_raw = open("output.txt", "w") for t in range(0, 30): # ns # for t in np.arange(0.0, 30.0, 0.1): # ns p = create_singlet_state() add_switch_to_singlet_triplet_basis_gate_to_program(p) w_larmor = 0.46 # 4.6e8 1/s as determined in the experiment p.inst(PHASE(w_larmor * t, 0)) p.inst(("SWITCH_TO_SINGLET_TRIPLET_BASIS", 0, 1)) wavefunction = qvm.wavefunction(p) probs = wavefunction.get_outcome_probs() p.measure(0, 0) p.measure(1, 1) # Run the code on a perfect QVM (no noise) data = qvm.run(p, trials=1024) # simulate physical noise on QVM singlet_noisy = [] triplet_noisy = [] state11_noisy = [] state00_noisy = [] for i in range(0, 3): data_noisy = qvm_noisy.run(p, trials=1000) noisy_data_distr = distribution(data_noisy) singlet_noisy.append(noisy_data_distr[(1, 0)]) triplet_noisy.append(noisy_data_distr[(0, 1)]) state11_noisy.append(noisy_data_distr[(1, 1)]) state00_noisy.append(noisy_data_distr[(0, 0)]) # Run the code on QPU singlet_qpu = [] triplet_qpu = [] state11_qpu = [] state00_qpu = [] # Suppress print statements _old_stdout = sys.stdout for i in range(0, 9): with open(os.devnull, 'w') as fp: sys.stdout = fp data_qpu = qpu.run(p, trials=1024) qpu_data_distr = distribution(data_qpu) singlet_qpu.append(qpu_data_distr[(1, 0)]) triplet_qpu.append(qpu_data_distr[(0, 1)]) state11_qpu.append(qpu_data_distr[(1, 1)]) state00_qpu.append(qpu_data_distr[(0, 0)]) sys.stdout = _old_stdout # print('compiled quil', job.compiled_quil()) # print('gate volume', job.gate_volume()) # print('gate depth', job.gate_depth()) # print('topological swaps', job.topological_swaps()) # print('program fidelity', job.program_fidelity()) # print('multiqubit gate depth', job.multiqubit_gate_depth()) # Note the order of qubit in Rigetti # http://pyquil.readthedocs.io/en/latest/qvm.html#multi-qubit-basis-enumeration # (1, 0) is singlet, but in string notation it is reversed ('01'), because # # "The Rigetti QVM enumerates bitstrings such that qubit 0 is the least significant bit (LSB) # and therefore on the right end of a bitstring" # print("%s, Noise, Singlet, %s" % (t, singlet_noisy), file=fp_raw) print("%s, Noise, Triplet, %s" % (t, triplet_noisy), file=fp_raw) print("%s, Noise, 00, %s" % (t, state00_noisy), file=fp_raw) print("%s, Noise, 11, %s" % (t, state11_noisy), file=fp_raw) print("%s, QPU, Singlet, %s" % (t, singlet_qpu), file=fp_raw) print("%s, QPU, Triplet, %s" % (t, triplet_qpu), file=fp_raw) print("%s, QPU, 00, %s" % (t, state00_qpu), file=fp_raw) print("%s, QPU, 11, %s" % (t, state11_qpu), file=fp_raw) print( "%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s" % ( t, probs['01'], probs['10'], distribution(data).get((1, 0), 0), distribution(data).get((0, 1), 0), np.mean(singlet_noisy), np.std(singlet_noisy), np.mean(triplet_noisy), np.std(triplet_noisy), np.mean(state00_noisy), np.std(state00_noisy), np.mean(state11_noisy), np.std(state11_noisy), np.mean(singlet_qpu), np.std(singlet_qpu), np.mean(triplet_qpu), np.std(triplet_qpu), np.mean(state00_qpu), np.std(state00_qpu), np.mean(state11_qpu), np.std(state11_qpu), ))