def test_nesting_a_program_inside_itself(): p = Program(H(0)).measure(0, 0) with pytest.raises(ValueError): p.if_then(0, p)
def test_kraus(): pq = Program(X(0)) pq.define_noisy_gate("X", (0, ), [[[0., 1.], [1., 0.]], [[0., 0.], [0., 0.]]]) pq.inst(X(1)) pq.define_noisy_gate("X", (1, ), [[[0., 1.], [1., 0.]], [[0., 0.], [0., 0.]]]) ret = pq.out() assert ret == """X 0 PRAGMA ADD-KRAUS X 0 "(0.0 1.0 1.0 0.0)" PRAGMA ADD-KRAUS X 0 "(0.0 0.0 0.0 0.0)" X 1 PRAGMA ADD-KRAUS X 1 "(0.0 1.0 1.0 0.0)" PRAGMA ADD-KRAUS X 1 "(0.0 0.0 0.0 0.0)" """ # test error due to bad normalization with pytest.raises(ValueError): pq.define_noisy_gate("X", (0, ), [[[0., 1.], [1., 0.]], [[0., 1.], [1., 0.]]]) # test error due to bad shape of kraus op with pytest.raises(ValueError): pq.define_noisy_gate( "X", (0, ), [[[0., 1., 0.], [1., 0., 0.]], [[0., 1.], [1., 0.]]]) pq1 = Program(X(0)) pq1.define_noisy_gate("X", (0, ), [[[0., 1.], [1., 0.]], [[0., 0.], [0., 0.]]]) pq2 = Program(X(1)) pq2.define_noisy_gate("X", (1, ), [[[0., 1.], [1., 0.]], [[0., 0.], [0., 0.]]]) assert pq1 + pq2 == pq pq_nn = Program(X(0)) pq_nn.no_noise() pq_nn.inst(X(1)) assert pq_nn.out() == """X 0
def test_if_then_inherits_defined_gates(): p1 = Program() p1.inst(H(0)) p1.measure(0, 0) p2 = Program() p2.defgate("A", np.array([[1., 0.], [0., 1.]])) p2.inst(("A", 0)) p3 = Program() p3.defgate("B", np.array([[0., 1.], [1., 0.]])) p3.inst(("B", 0)) p1.if_then(0, p2, p3) assert p2.defined_gates[0] in p1.defined_gates assert p3.defined_gates[0] in p1.defined_gates
def test_multiple_instantiate(): p = Program() q = p.alloc() p.inst(H(q)) assert p.out() == 'H 0\n' assert p.out() == 'H 0\n'
def test_quantum_gate_shift(): prog = Program(X(0), CNOT(0, 4), MEASURE(5, [5])) assert shift_quantum_gates(prog, 5) == Program(X(5), CNOT(5, 9), MEASURE(5, [5]))
return 1 def get_compiled_prog_1(): return Program([ RX(pi/2, 0), I(0), RZ(-pi/2, 0), RX(-pi/2, 0), I(0), RZ(pi/2, 0), ]) p = Program() p.inst(X(0)) # want increasing number of I-gates p.define_noisy_gate( "II", [0], append_damping_to_gate(np.eye(2), damping_per_I)) p.inst([I(0) for _ in range(num_I)]) # p.inst(H(0)) p.inst(MEASURE(0, [0])) #print("Expected 1 %s" % qvm.run(p, [0])) thetas = np.linspace(-pi, pi, num=20) t1s = np.logspace(-6, -5, num=3) # print(t1s[0]) prog = get_compiled_prog(pi/2)
# f0 qram = Program( X(10), CNOT(2, 6), CNOT(6, 10), CCNOT(6, 4, 5), CCNOT(1, 6, 4), CCNOT(1, 10, 8), CNOT(8, 10), CNOT(4, 6), CCNOT(0, 4, 3), CCNOT(0, 6, 5), CCNOT(0, 8, 7), CCNOT(0, 10, 9), CNOT(9, 10), CNOT(7, 8), CNOT(5, 6), CNOT(3, 4), CCNOT(10, 18, 19), CCNOT(9, 17, 19), CCNOT(8, 16, 19), CCNOT(7, 15, 19), CCNOT(6, 14, 19), CCNOT(5, 13, 19), CCNOT(4, 12, 19), CCNOT(3, 11, 19), )
def test_program_tuple(): p = Program() p.inst(("Y", 0), ("X", 1)) assert len(p) == 2 assert p.out() == "Y 0\nX 1\n"
def test_prog_init(): p = Program() p.inst(X(0)).measure(0, 0) assert p.out() == 'X 0\nMEASURE 0 [0]\n'
def test_plus_operator(): p = Program() p += H(0) p += [X(0), Y(0), Z(0)] assert len(p) == 4 assert p.out() == "H 0\nX 0\nY 0\nZ 0\n"
def test_iteration(): gate_list = [H(0), Y(1), CNOT(0, 1)] program = Program(gate_list) for ii, instruction in enumerate(program): assert instruction == gate_list[ii]
def test_len_nested(): p = Program(H(0)).measure(0, 0) q = Program(H(0), CNOT(0, 1)) p.if_then(0, q) assert len(p) == 8
def test_len_one(): prog = Program(X(0)) assert len(prog) == 1
def bell_p(a, b): p = Program() p.inst(H(a)) p.inst(CNOT(a, b)) return p
def __init__(self, qc, file_prefix, num_bits, hamil, all_var_nums, fun_name_to_fun, do_resets=True, **kwargs): """ Constructor Do in constructor as much hamil indep stuff as possible so don't have to redo it with every call to cost fun. Also, when self.num_samples !=0, we store a dict called term_to_exec mapping an executable (output of Rigetti compile() function) to a term, for each term in the hamiltonian hamil. When num_samples=0, term_to_exec={} Parameters ---------- qc : QuantumComputer file_prefix : str num_bits : int hamil : QubitOperator all_var_nums : list[int] fun_name_to_fun : dict[str, function] do_resets : bool kwargs : dict key-words args of MeanHamilMinimizer constructor Returns ------- """ MeanHamil.__init__(self, file_prefix, num_bits, hamil, all_var_nums, fun_name_to_fun, **kwargs) self.qc = qc self.do_resets = do_resets # this creates a file with all PyQuil gates that # are independent of hamil. Gates may contain free parameters self.translator = Qubiter_to_RigettiPyQuil( self.file_prefix, self.num_bits, aqasm_name='RigPyQuil', prelude_str='', ending_str='') with open(self.translator.aqasm_path, 'r') as fi: self.translation_line_list = fi.readlines() pg = Program() self.pg = pg if self.num_samples: # pg prelude pg += Pragma('INITIAL_REWIRING', ['"PARTIAL"']) if self.do_resets: pg += RESET() ro = pg.declare('ro', 'BIT', self.num_bits) s = '' for var_num in self.all_var_nums: vname = self.translator.vprefix + str(var_num) s += vname s += ' = pg.declare("' s += vname s += '", memory_type="REAL")\n' exec(s) # add to pg the operations that are independent of hamil for line in self.translation_line_list: line = line.strip('\n') if line: exec(line) len_pg_in = len(pg) # hamil loop to store executables for each term in hamil self.term_to_exec = {} for term, coef in self.hamil.terms.items(): # reset pg to initial length. # Temporary work-around to bug # in PyQuil ver 2.5.0. # Slicing was changing # pg from type Program to type list pg = Program(pg[:len_pg_in]) self.pg = pg # add xy measurements coda to pg bit_pos_to_xy_str =\ {bit: action for bit, action in term if action != 'Z'} RigettiTools.add_xy_meas_coda_to_program( pg, bit_pos_to_xy_str) # request measurements for i in range(self.num_bits): pg += MEASURE(i, ro[i]) pg.wrap_in_numshots_loop(shots=self.num_samples) executable = self.qc.compile(pg) # print(",,,...", executable) self.term_to_exec[term] = executable
def test_classical_regs(): p = Program() p.inst(X(0)).measure(0, 1) assert p.out() == 'X 0\nMEASURE 0 [1]\n'
from pyquil.quil import Program from pyquil.gates import H, X, CNOT, MEASURE from pyquil.api import SyncConnection # Reference: https://arxiv.org/pdf/1302.4310.pdf p = Program() p.inst("""DEFGATE CH(%theta): 1, 0, 0, 0 0, 1, 0, 0 0, 0, cos(2*%theta), sin(2*%theta) 0, 0, sin(2*%theta), cos(-2*%theta)""") p.inst(H(3)) p.inst(CNOT(3, 2)) p.inst(CNOT(2, 1)) p.inst("CH(pi/8) 1 0") p.inst("CH(pi/16) 2 0") p.inst(H(1)) p.inst(H(2)) p.inst(X(0)) p.inst(MEASURE(0)) p.inst(MEASURE(1)) p.inst(MEASURE(2)) # run the program on a QVM qvm = SyncConnection() wvf, _ = qvm.wavefunction(p) print(wvf)
def test_simple_instructions(): p = Program().inst(HALT, WAIT, RESET, NOP) assert p.out() == 'HALT\nWAIT\nRESET\nNOP\n'
from pyquil.quil import Program p = Program() """ Gate definitions """ p.inst("""DEFGATE CRX(%theta): 1, 0, 0, 0 0, 1, 0, 0 0, 0, cos(%theta/2), -i*sin(%theta/2) 0, 0, -i*sin(%theta/2), cos(%theta/2)""") p.inst("""DEFGATE CRY(%theta): 1, 0, 0, 0 0, 1, 0, 0 0, 0, cos(%theta/2), -sin(%theta/2) 0, 0, sin(%theta/2), cos(%theta/2)""") p.inst("""DEFGATE CRZ(%theta): 1, 0, 0, 0 0, 1, 0, 0 0, 0, e^(-i*%theta/2), 0 0, 0, 0, e^(i*%theta/2)""")
def test_unary_classicals(): p = Program() p.inst(TRUE(0), FALSE(Addr(1)), NOT(2)) assert p.out() == 'TRUE [0]\n' \ 'FALSE [1]\n' \ 'NOT [2]\n'
def test_alloc(): p = Program() p.inst(H(0)) # H 0 q1 = p.alloc() # q1 = 1 q2 = p.alloc() # q2 = 3 p.inst(CNOT(q1, q2)) # CNOT 1 3 p.inst(H(2)) q3 = p.alloc() # q3 = 4 p.inst(X(q3)) # X 4 assert p.out() == "H 0\n" \ "CNOT 1 3\n" \ "H 2\n" \ "X 4\n"
def test_measurement_calls(): p = Program() p.inst(MEASURE(0, 1), MEASURE(0, Addr(1))) assert p.out() == 'MEASURE 0 [1]\n' * 2
def test_prog_merge(): prog_0 = Program(X(0)) prog_1 = Program(Y(0)) assert merge_programs([prog_0, prog_1]).out() == (prog_0 + prog_1).out()
def test_measure_all(): p = Program() p.measure_all((0, 0), (1, 1), (2, 3)) assert p.out() == 'MEASURE 0 [0]\n' \ 'MEASURE 1 [1]\n' \ 'MEASURE 2 [3]\n'
def test_get_qubits(): pq = Program(X(0), CNOT(0, 4), MEASURE(5, [5])) assert pq.get_qubits() == {0, 4, 5} qq = pq.alloc() pq.inst(Y(2), X(qq)) assert pq.get_qubits() == {0, 1, 2, 4, 5} # this synthesizes the allocation qubit_index = 1 p = Program(("H", qubit_index)) assert p.get_qubits() == {qubit_index} q1 = p.alloc() q2 = p.alloc() p.inst(("CNOT", q1, q2)) assert p.get_qubits() == {qubit_index, 0, 2}
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'
def test_define_noisy_readout(): pq = Program(X(0)) pq.define_noisy_readout(0, .8, .9) pq.inst(X(1)) pq.define_noisy_readout(1, .9, .8) ret = pq.out() assert ret == """X 0 PRAGMA READOUT-POVM 0 "(0.8 0.09999999999999998 0.19999999999999996 0.9)" X 1 PRAGMA READOUT-POVM 1 "(0.9 0.19999999999999996 0.09999999999999998 0.8)" """ # test error due to bad normalization with pytest.raises(ValueError): pq.define_noisy_readout(0, 1.1, .5) # test error due to bad normalization with pytest.raises(ValueError): pq.define_noisy_readout(0, .5, 1.5) # test error due to negative probability with pytest.raises(ValueError): pq.define_noisy_readout(0, -0.1, .5) # test error due to negative probability with pytest.raises(ValueError): pq.define_noisy_readout(0, .5, -1.) # test error due to bad qubit_index value with pytest.raises(ValueError): pq.define_noisy_readout(-1, .5, .5) # test error due to bad qubit_index type with pytest.raises(TypeError): pq.define_noisy_readout(1., .5, .5)
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'
def test_installing_programs_inside_other_programs(): p = Program() q = Program() p.inst(q) assert len(p) == 0
def test_rotations(): p = Program(RX(0.5)(0), RY(0.1)(1), RZ(1.4)(2)) assert p.out() == 'RX(0.5) 0\nRY(0.1) 1\nRZ(1.4) 2\n'
def test_inline_alloc(): p = Program() p += H(p.alloc()) assert p.out() == "H 0\n"
def test_controlled_gates(): p = Program(CNOT(0, 1), CCNOT(0, 1, 2)) assert p.out() == 'CNOT 0 1\nCCNOT 0 1 2\n'
from pyquil.quil import Program from pyquil.parameters import Parameter, cos, sin, exp import numpy as np p = Program() """ Gate definitions """ theta = Parameter('theta') crx = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, cos(theta / 2), -1j * sin(theta / 2)], [0, 0, -1j * sin(theta / 2), cos(theta / 2)]]) p = Program().defgate("CRX", crx, [theta]) cry = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, cos(theta / 2), -sin(theta / 2)], [0, 0, sin(theta / 2), cos(theta / 2)]]) p = Program().defgate("CRY", cry, [theta]) crz = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, exp(-1j*(theta/2)), 0], [0, 0, 0, exp(1j*(theta/2))]])
def test_swaps(): p = Program(SWAP(0, 1), CSWAP(0, 1, 2), ISWAP(0, 1), PSWAP(np.pi)(0, 1)) assert p.out() == 'SWAP 0 1\nCSWAP 0 1 2\nISWAP 0 1\nPSWAP(pi) 0 1\n'
# http://pyquil.readthedocs.io/en/latest/intro.html # Imports for pyQuil (ignore for now) import numpy as np from pyquil.quil import Program from pyquil.api import QVMConnection quantum_simulator = QVMConnection() # pyQuil is based around operations (or gates) so we will start with the most # basic one: the identity operation, called I. I takes one argument, the index # of the qubit that it should be applied to. from pyquil.gates import * # Make a quantum program that allocates one qubit (qubit #0) and does nothing to it p = Program(I(0)) print(p.inst(X(0))) # Quantum states are called wavefunctions for historical reasons. # We can run this basic program on our connection to the simulator. # This call will return the state of our qubits after we run program p. # This api call returns a tuple, but we'll ignore the second value for now. wavefunction = quantum_simulator.wavefunction(p) # wavefunction is a Wavefunction object that stores a quantum state as a list of amplitudes alpha, beta = wavefunction print("Our qubit is in the state alpha={} and beta={}".format(alpha, beta)) print("The probability of measuring the qubit in outcome 0 is {}".format(abs(alpha)**2)) print("The probability of measuring the qubit in outcome 1 is {}".format(abs(beta)**2))
def test_control_flows(): classical_flag_register = 2 p = Program(X(0), H(0)).measure(0, classical_flag_register) # run p in a loop until classical_flag_register is 0 loop_prog = Program(X(0)).measure(0, classical_flag_register) loop_prog.while_do(classical_flag_register, p) assert loop_prog.out() == 'X 0\nMEASURE 0 [2]\nLABEL @START1\nJUMP-UNLESS @END2 [2]\nX ' \ '0\nH 0\nMEASURE 0 [2]\nJUMP @START1\nLABEL @END2\n' # create a program that branches based on the value of a classical register x_prog = Program(X(0)) z_prog = Program() branch = Program(H(1)).measure(1, 1).if_then(1, x_prog, z_prog).measure(0, 0) assert branch.out() == 'H 1\nMEASURE 1 [1]\nJUMP-WHEN @THEN1 [1]\nJUMP @END2\nLABEL ' \ '@THEN1\nX 0\nLABEL @END2\nMEASURE 0 [0]\n'
from pyquil.quil import Program #from pyquil.api import QPUConnection from pyquil.api import QVMConnection from pyquil.gates import * qvm = QVMConnection() ins = Program() ins.inst(H(1), CNOT(1, 2)) # Creating B00 ins.inst(CNOT(0, 1), H(0)) ins.measure(0, 0).measure(1, 1).if_then(1, X(2)).if_then(0, Z(2)) wvf = qvm.wavefunction(ins, [0, 1]) #print( wvf) ins = Program( H(0), H(1), CNOT(1, 2), CNOT(0, 1), H(0), ) ins.measure(0, 0).measure(1, 1).if_then(1, X(2)).if_then(1, Z(2)) wvf = qvm.wavefunction(ins) print(ins) result = qvm.run_and_measure(ins, [2]) print(result)
def test_if_option(): p = Program(X(0)).measure(0, 0).if_then(0, Program(X(1))) assert p.out() == 'X 0\nMEASURE 0 [0]\nJUMP-WHEN @THEN1 [0]\nJUMP @END2\n' \ 'LABEL @THEN1\nX 1\nLABEL @END2\n' assert isinstance(p.instructions[2], JumpWhen)
from pyquil.quil import Program from pyquil.gates import * from pyquil.parameters import Parameter, quil_sin, quil_cos from pyquil.quilbase import DefGate #from pyquil.api import QVMConnection from referenceqvm.api import QVMConnection import numpy as np theta = Parameter('theta') cry = np.array([[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, quil_cos( theta / 2), -1 * quil_sin(theta / 2)], [0.0, 0.0, quil_sin(theta / 2), quil_cos(theta / 2)]]) dg = DefGate('CRY', cry, [theta]) CRY = dg.get_constructor() p = Program() p.inst(dg) p.inst(X(0)) p.inst(X(1)) p.inst(CRY(4.304)(0, 2)) qvm = QVMConnection() wf = qvm.wavefunction(p) print(wf)
from pyquil.quil import Program import pyquil.api as api from pyquil.gates import * qvm = api.QVMConnection() p = Program() p.inst(H(0), CNOT(0, 1), MEASURE(1, [1])) wavefunction = qvm.wavefunction(p) print(wavefunction)