def test_reset(forest): device = NxDevice(nx.complete_graph(3)) qc = QuantumComputer(name='testy!', qam=QVM(connection=forest), device=device, compiler=DummyCompiler()) p = Program(Declare(name='theta', memory_type='REAL'), Declare(name='ro', memory_type='BIT'), RX(MemoryReference('theta'), 0), MEASURE(0, MemoryReference('ro'))).wrap_in_numshots_loop(1000) qc.run(executable=p, memory_map={'theta': [np.pi]}) aref = ParameterAref(name='theta', index=0) assert qc.qam._variables_shim[aref] == np.pi assert qc.qam._executable == p assert qc.qam._memory_results["ro"].shape == (1000, 1) assert all([bit == 1 for bit in qc.qam._memory_results["ro"]]) assert qc.qam.status == 'done' qc.reset() assert qc.qam._variables_shim == {} assert qc.qam._executable is None assert qc.qam._memory_results["ro"] is None assert qc.qam.status == 'connected'
def test_classical_regs_implicit_ro(): p = Program() p.inst(Declare("reg", "BIT", 2), X(0)).measure(0, MemoryReference("reg", 1)) assert p.out() == "DECLARE reg BIT[2]\nX 0\nMEASURE 0 reg[1]\n" assert p.declarations == { "ro": Declare("ro", "BIT", 1), "reg": Declare("reg", "BIT", 2), }
def test_parsing_raw_capture(): parse_equals( "DECLARE iqs REAL[200000]\n" 'RAW-CAPTURE 0 "ro_rx" 0.001 iqs', Declare("iqs", "REAL", 200000), RawCapture(Frame([Qubit(0)], "ro_rx"), 0.001, MemoryReference("iqs")), ) parse_equals( "DECLARE iqs REAL[200000]\n" 'NONBLOCKING RAW-CAPTURE 0 "ro_rx" 0.001 iqs', Declare("iqs", "REAL", 200000), RawCapture(Frame([Qubit(0)], "ro_rx"), 0.001, MemoryReference("iqs"), nonblocking=True), )
def test_unsupported_ops(): target = Label("target") base_prog = Program(Declare("reg1", "BIT"), Declare("reg2", "BIT"), H(0), JumpTarget(target), CNOT(0, 1)) bad_ops = [WAIT, Jump(target), MOVE(MemoryReference("reg1"), MemoryReference("reg2"))] assert to_latex(base_prog) for op in bad_ops: prog = base_prog + op with pytest.raises(ValueError): _ = to_latex(prog)
def test_parsing_capture(): wf = FlatWaveform(duration=1.0, iq=1.0) parse_equals( "DECLARE iq REAL[2]\n" 'CAPTURE 0 "ro_rx" flat(duration: 1.0, iq: 1.0) iq', Declare("iq", "REAL", 2), Capture(Frame([Qubit(0)], "ro_rx"), wf, MemoryReference("iq")), ) parse_equals( "DECLARE iq REAL[2]\n" 'NONBLOCKING CAPTURE 0 "ro_rx" flat(duration: 1.0, iq: 1.0) iq', Declare("iq", "REAL", 2), Capture(Frame([Qubit(0)], "ro_rx"), wf, MemoryReference("iq"), nonblocking=True), )
def test_halt(): prog = Program(Declare("ro", "BIT"), X(0), MEASURE(0, MemoryReference("ro", 0))) prog.inst(HALT) prog.inst(X(0), MEASURE(0, MemoryReference("ro", 0))) qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) # HALT should stop execution; measure should give 1 assert qam.ram["ro"][0] == 1 prog = Program(Declare("ro", "BIT"), X(0)).inst(X(0)).inst(MEASURE(0, MemoryReference("ro", 0))) qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) assert qam.ram["ro"][0] == 0
def test_construction_syntax(): p = (Program().inst(Declare("ro", "BIT", 2), X(0), Y(1), Z(0)).measure(0, MemoryReference("ro", 1))) assert p.out() == ("DECLARE ro BIT[2]\nX 0\nY 1\nZ 0\nMEASURE 0 ro[1]\n") p = (Program().inst(Declare("ro", "BIT", 3), X(0)).inst(Y(1)).measure( 0, MemoryReference("ro", 1)).inst(MEASURE(1, MemoryReference("ro", 2)))) assert p.out() == ( "DECLARE ro BIT[3]\nX 0\nY 1\nMEASURE 0 ro[1]\nMEASURE 1 ro[2]\n") p = (Program().inst(Declare("ro", "BIT", 2), X(0)).measure(0, MemoryReference("ro", 1)).inst( Y(1), X(0)).measure(0, MemoryReference("ro", 0))) assert p.out() == ( "DECLARE ro BIT[2]\nX 0\nMEASURE 0 ro[1]\nY 1\nX 0\nMEASURE 0 ro[0]\n")
def test_run_with_parameters(forest): device = NxDevice(nx.complete_graph(3)) qc = QuantumComputer(name='testy!', qam=QVM(connection=forest), device=device, compiler=DummyCompiler()) bitstrings = qc.run(executable=Program( Declare(name='theta', memory_type='REAL'), Declare(name='ro', memory_type='BIT'), RX(MemoryReference('theta'), 0), MEASURE(0, MemoryReference('ro'))).wrap_in_numshots_loop(1000), memory_map={'theta': [np.pi]}) assert bitstrings.shape == (1000, 1) assert all([bit == 1 for bit in bitstrings])
def test_indexing(): program = (Program(Declare("ro", "BIT"), H(0), Y(1), CNOT(0, 1)).measure( 0, MemoryReference("ro", 0)).if_then(MemoryReference("ro", 0), Program(X(0)), Program())) assert program[1] == H(0) for ii, instr in enumerate(program.instructions): assert program[ii] == instr
def test_readout_symmetrization(client_configuration: QCSClientConfiguration): quantum_processor = NxQuantumProcessor(nx.complete_graph(3)) noise_model = decoherence_noise_with_asymmetric_ro(quantum_processor.to_compiler_isa()) qc = QuantumComputer( name="testy!", qam=QVM(client_configuration=client_configuration, noise_model=noise_model), compiler=DummyCompiler(quantum_processor=quantum_processor, client_configuration=client_configuration), ) prog = Program( Declare("ro", "BIT", 2), I(0), X(1), MEASURE(0, MemoryReference("ro", 0)), MEASURE(1, MemoryReference("ro", 1)), ) prog.wrap_in_numshots_loop(1000) bs1 = qc.run(prog) avg0_us = np.mean(bs1[:, 0]) avg1_us = 1 - np.mean(bs1[:, 1]) diff_us = avg1_us - avg0_us assert diff_us > 0.03 prog = Program( I(0), X(1), ) bs2 = qc.run_symmetrized_readout(prog, 1000) avg0_s = np.mean(bs2[:, 0]) avg1_s = 1 - np.mean(bs2[:, 1]) diff_s = avg1_s - avg0_s assert diff_s < 0.05
def test_qvm_run_region_declared_not_measured( client_configuration: QCSClientConfiguration): qvm = QVM(client_configuration=client_configuration) p = Program(Declare("reg", "BIT"), X(0)) result = qvm.run(p.wrap_in_numshots_loop(100)) bitstrings = result.readout_data.get("reg") assert bitstrings.shape == (100, 0)
def test_qvm_run_region_declared_not_measured(forest: ForestConnection): qvm = QVM(connection=forest) p = Program(Declare("reg", "BIT"), X(0)) nq = PyQuilExecutableResponse(program=p.out(), attributes={"num_shots": 100}) qvm.load(nq).run().wait() bitstrings = qvm.read_memory(region_name="reg") assert bitstrings.shape == (100, 0)
def test_qvm_run_region_declared_not_measured( client_configuration: QCSClientConfiguration): qvm = QVM(client_configuration=client_configuration) p = Program(Declare("reg", "BIT"), X(0)) qvm.load(p.wrap_in_numshots_loop(100)).run().wait() bitstrings = qvm.read_memory(region_name="reg") assert bitstrings.shape == (100, 0)
def test_measurement_calls(): p = Program() p.inst(Declare('ro', 'BIT', 2), MEASURE(0, MemoryReference('ro', 1)), MEASURE(0, MemoryReference('ro', 1))) assert p.out() == ('DECLARE ro BIT[2]\n' 'MEASURE 0 ro[1]\n' 'MEASURE 0 ro[1]\n')
def declare(self, name, memory_type='BIT', memory_size=1, shared_region=None, offsets=None): """DECLARE a quil variable This adds the declaration to the current program and returns a MemoryReference to the base (offset = 0) of the declared memory. .. note:: This function returns a MemoryReference and cannot be chained like some of the other Program methods. Consider using ``inst(DECLARE(...))`` if you would like to chain methods, but please be aware that you must create your own MemoryReferences later on. :param name: Name of the declared variable :param memory_type: Type of the declared memory: 'BIT', 'REAL', 'OCTET' or 'INTEGER' :param memory_size: Number of array elements in the declared memory. :param shared_region: You can declare a variable that shares its underlying memory with another region. This allows aliasing. For example, you can interpret an array of measured bits as an integer. :param offsets: If you are using ``shared_region``, this allows you to share only a part of the parent region. The offset is given by an array type and the number of elements of that type. For example, ``DECLARE target-bit BIT SHARING real-region OFFSET 1 REAL 4 BIT`` will let you use target-bit to poke into the fourth bit of the second real from the leading edge of real-region. :return: a MemoryReference to the start of the declared memory region, ie a memory reference to ``name[0]``. """ self.inst(Declare(name=name, memory_type=memory_type, memory_size=memory_size, shared_region=shared_region, offsets=offsets)) return MemoryReference(name=name, declared_size=memory_size)
def test_memory_commands(): parse_equals("DECLARE mem OCTET[32] SHARING mem2 OFFSET 16 REAL OFFSET 32 REAL", Declare("mem", "OCTET", 32, shared_region="mem2", offsets=[(16, "REAL"), (32, "REAL")])) parse_equals("STORE mem ro[2] ro[0]", STORE("mem", MemoryReference("ro", 2), MemoryReference("ro", 0))) parse_equals("LOAD ro[8] mem mem[4]", LOAD(MemoryReference("ro", 8), "mem", MemoryReference("mem", 4))) parse_equals("CONVERT ro[1] ro[2]", CONVERT(MemoryReference("ro", 1), MemoryReference("ro", 2))) parse_equals("EXCHANGE ro[0] ro[1]", EXCHANGE(MemoryReference("ro", 0), MemoryReference("ro", 1))) parse_equals("MOVE mem[2] 4", MOVE(MemoryReference("mem", 2), 4))
def test_warn_on_pragma_with_trailing_measures(): "Check that to_latex warns when measurement alignment conflicts with gate group pragma." with pytest.warns(UserWarning): _ = to_latex(Program(Declare('ro', 'BIT'), Pragma("LATEX_GATE_GROUP"), MEASURE(0, MemoryReference('ro')), Pragma("END_LATEX_GATE_GROUP"), MEASURE(1, MemoryReference('ro'))))
def test_qvm_run_just_program(client_configuration: QCSClientConfiguration): qvm = QVM(client_configuration=client_configuration, gate_noise=(0.01, 0.01, 0.01)) p = Program(Declare("ro", "BIT"), X(0), MEASURE(0, MemoryReference("ro"))) result = qvm.run(p.wrap_in_numshots_loop(1000)) bitstrings = result.readout_data.get("ro") assert bitstrings.shape == (1000, 1) assert np.mean(bitstrings) > 0.8
def test_qvm__default_client(client_configuration: QCSClientConfiguration): qvm = QVM(client_configuration=client_configuration) p = Program(Declare("ro", "BIT"), X(0), MEASURE(0, MemoryReference("ro"))) qvm.load(p.wrap_in_numshots_loop(1000)) qvm.run() qvm.wait() bitstrings = qvm.read_memory(region_name="ro") assert bitstrings.shape == (1000, 1)
def test_run_with_parameters(forest): device = NxDevice(nx.complete_graph(3)) qc = QuantumComputer( name="testy!", qam=QVM(connection=forest), device=device, compiler=DummyCompiler() ) bitstrings = qc.run( executable=Program( Declare(name="theta", memory_type="REAL"), Declare(name="ro", memory_type="BIT"), RX(MemoryReference("theta"), 0), MEASURE(0, MemoryReference("ro")), ).wrap_in_numshots_loop(1000), memory_map={"theta": [np.pi]}, ) assert bitstrings.shape == (1000, 1) assert all([bit == 1 for bit in bitstrings])
def test_measurement_calls(): p = Program() p.inst( Declare("ro", "BIT", 2), MEASURE(0, MemoryReference("ro", 1)), MEASURE(0, MemoryReference("ro", 1)), ) assert p.out() == ("DECLARE ro BIT[2]\nMEASURE 0 ro[1]\nMEASURE 0 ro[1]\n")
def implicitly_declare_ro( instructions: List[AbstractInstruction]) -> List[AbstractInstruction]: """ Implicitly declare a register named ``ro`` for backwards compatibility with Quil 1. There used to be one un-named hunk of classical memory. Now there are variables with declarations. Instead of:: MEASURE 0 [0] You must now measure into a named register, idiomatically:: MEASURE 0 ro[0] The ``MEASURE`` instruction will emit this (with a deprecation warning) if you're still using bare integers for classical addresses. However, you must also declare memory in the new scheme:: DECLARE ro BIT[8] MEASURE 0 ro[0] This method will determine if you are in "backwards compatibility mode" and will declare a read-out ``ro`` register for you. If you program contains any DECLARE commands or if it does not have any MEASURE x ro[x], this will not do anything. This behavior is included for backwards compatibility and will be removed in future releases of PyQuil. Please DECLARE all memory including ``ro``. """ ro_addrs: List[int] = [] for instr in instructions: if isinstance(instr, Declare): # The user has declared their own memory # so they are responsible for all declarations and memory references. return instructions if isinstance(instr, Measurement): if instr.classical_reg is None: continue if instr.classical_reg.name == "ro": ro_addrs += [instr.classical_reg.offset] else: # The user has used a classical register named something other than "ro" # so they are responsible for all declarations and memory references. return instructions if len(ro_addrs) == 0: return instructions warnings.warn( "Please DECLARE all memory. I'm adding a declaration for the `ro` register, " "but I won't do this for you in the future.") new_instr = instructions.copy() new_instr.insert( 0, Declare(name="ro", memory_type="BIT", memory_size=max(ro_addrs) + 1)) return new_instr
def test_is_protoquil(): prog = Program(Declare('ro', 'BIT'), MEASURE(1, MemoryReference("ro", 0)), H(1), RESET()) validate_protoquil(prog) assert prog.is_protoquil() prog = Program(Declare('ro', 'BIT'), H(0), Y(1), CNOT(0, 1)) \ .measure(0, MemoryReference("ro", 0)) \ .if_then(MemoryReference("ro", 0), Program(X(0)), Program()) with pytest.raises(ValueError): validate_protoquil(prog) assert not prog.is_protoquil() prog = Program(Declare('ro', 'BIT'), ClassicalNot(MemoryReference("ro", 0))) with pytest.raises(ValueError): validate_protoquil(prog) assert not prog.is_protoquil()
def test_run_with_bad_parameters(client_configuration: QCSClientConfiguration, param): quantum_processor = NxQuantumProcessor(nx.complete_graph(3)) qc = QuantumComputer( name="testy!", qam=QVM(client_configuration=client_configuration), compiler=DummyCompiler(quantum_processor=quantum_processor, client_configuration=client_configuration), ) executable = Program( Declare(name="theta", memory_type="REAL"), Declare(name="ro", memory_type="BIT"), RX(MemoryReference("theta"), 0), MEASURE(0, MemoryReference("ro")), ).wrap_in_numshots_loop(1000) with pytest.raises(TypeError, match=r"Parameter must be"): executable.write_memory(region_name="theta", value=param)
def declare(self, name, memory_type, memory_size, *sharing): shared, *offsets = sharing d = Declare( str(name), memory_type=str(memory_type), memory_size=int(memory_size) if memory_size else 1, shared_region=str(shared) if shared else None, offsets=offsets if shared else None, ) return d
def test_run_with_parameters(client_configuration: QCSClientConfiguration): quantum_processor = NxQuantumProcessor(nx.complete_graph(3)) qc = QuantumComputer( name="testy!", qam=QVM(client_configuration=client_configuration), compiler=DummyCompiler(quantum_processor=quantum_processor, client_configuration=client_configuration), ) bitstrings = qc.run( executable=Program( Declare(name="theta", memory_type="REAL"), Declare(name="ro", memory_type="BIT"), RX(MemoryReference("theta"), 0), MEASURE(0, MemoryReference("ro")), ).wrap_in_numshots_loop(1000), memory_map={"theta": [np.pi]}, ) assert bitstrings.shape == (1000, 1) assert all([bit == 1 for bit in bitstrings])
def test_noisy(client_configuration: QCSClientConfiguration): # https://github.com/rigetti/pyquil/issues/764 p = Program( Declare("ro", "BIT", 1), X(0), MEASURE(0, ("ro", 0)), ).wrap_in_numshots_loop(10000) qc = get_qc("1q-qvm", noisy=True, client_configuration=client_configuration) result = qc.run(qc.compile(p)) assert result.mean() < 1.0
def test_qvm_run_just_program(client_configuration: QCSClientConfiguration): qvm = QVM(client_configuration=client_configuration, gate_noise=(0.01, 0.01, 0.01)) p = Program(Declare("ro", "BIT"), X(0), MEASURE(0, MemoryReference("ro"))) qvm.load(p.wrap_in_numshots_loop(1000)) qvm.run() qvm.wait() bitstrings = qvm.read_memory(region_name="ro") assert bitstrings.shape == (1000, 1) assert np.mean(bitstrings) > 0.8
def test_get_qubits(): pq = Program(Declare('ro', 'BIT'), X(0), CNOT(0, 4), MEASURE(5, MemoryReference("ro", 0))) assert pq.get_qubits() == {0, 4, 5} q = [QubitPlaceholder() for _ in range(6)] pq = Program(Declare('ro', 'BIT'), X(q[0]), CNOT(q[0], q[4]), MEASURE(q[5], MemoryReference("ro", 0))) qq = QubitPlaceholder() pq.inst(Y(q[2]), X(qq)) assert address_qubits(pq).get_qubits() == {0, 1, 2, 3, 4} qubit_index = 1 p = Program(("H", qubit_index)) assert p.get_qubits() == {qubit_index} q1 = QubitPlaceholder() q2 = QubitPlaceholder() p.inst(("CNOT", q1, q2)) with pytest.raises(ValueError) as e: _ = address_qubits(p).get_qubits() assert e.match('Your program mixes instantiated qubits with placeholders')
def test_qvm_run_just_program(forest: ForestConnection): qvm = QVM(connection=forest, gate_noise=[0.01] * 3) p = Program(Declare("ro", "BIT"), X(0), MEASURE(0, MemoryReference("ro"))) p.wrap_in_numshots_loop(1000) qvm.load(p) qvm.run() qvm.wait() bitstrings = qvm.read_memory(region_name="ro") assert bitstrings.shape == (1000, 1) assert np.mean(bitstrings) > 0.8