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_measure_bitstrings(forest): device = NxDevice(nx.complete_graph(2)) qc_pyqvm = QuantumComputer(name="testy!", qam=PyQVM(n_qubits=2), device=device, compiler=DummyCompiler()) qc_forest = QuantumComputer( name="testy!", qam=QVM(connection=forest, gate_noise=[0.00] * 3), device=device, compiler=DummyCompiler(), ) prog = Program(I(0), I(1)) meas_qubits = [0, 1] sym_progs, flip_array = _symmetrization(prog, meas_qubits, symm_type=-1) results = _measure_bitstrings(qc_pyqvm, sym_progs, meas_qubits, num_shots=1) # test with pyQVM answer = [ np.array([[0, 0]]), np.array([[0, 1]]), np.array([[1, 0]]), np.array([[1, 1]]) ] assert all([np.allclose(x, y) for x, y in zip(results, answer)]) # test with regular QVM results = _measure_bitstrings(qc_forest, sym_progs, meas_qubits, num_shots=1) assert all([np.allclose(x, y) for x, y in zip(results, answer)])
def compile_rigetti(num_qubits, topology, program): if topology.lower() == 'ring': edge_list = [] for i in range(0, num_qubits): edge_list.append((i, (i + 1) % num_qubits)) topology = nx.from_edgelist(edge_list) device = NxDevice(topology) compiler = LocalQVMCompiler("http://localhost:6000", device) my_qc = QuantumComputer(name='my_qc', qam=QVM(connection=ForestConnection()), device=device, compiler=compiler) executable = compiler.quil_to_native_quil( program) #create QC compatible specification depth = compute_depth_rigetti(executable) volume = len(executable) - 3 #subtract extra directives print(executable) q2_count = two_qubit_count(executable) out_str = str(executable) out_str = out_str + ("#DEPTH: %s |VOL.: %s |2Q GATE COUNT: %s\n" % (depth, volume, q2_count)) print("DEPTH: %s |VOL.: %s |2Q GATE COUNT: %s" % (depth, volume, q2_count)) print() print() return out_str
def test_qc(): from pyquil.api import ForestConnection, QuantumComputer from pyquil.api._compiler import _extract_attribute_dictionary_from_program from pyquil.api._qac import AbstractCompiler from pyquil.device import NxDevice from pyquil.gates import I class BasicQVMCompiler(AbstractCompiler): def quil_to_native_quil(self, program: Program): return basic_compile(program) def native_quil_to_executable(self, nq_program: Program): return PyQuilExecutableResponse( program=nq_program.out(), attributes=_extract_attribute_dictionary_from_program( nq_program)) try: qc = QuantumComputer( name='testing-qc', qam=QVM(connection=ForestConnection(), random_seed=52), device=NxDevice(nx.complete_graph(2)), compiler=BasicQVMCompiler(), ) qc.run_and_measure(Program(I(0)), trials=1) return qc except (RequestException, TimeoutError) as e: return pytest.skip( "This test requires a running local QVM: {}".format(e))
def test_readout_symmetrization(forest): device = NxDevice(nx.complete_graph(3)) noise_model = decoherence_noise_with_asymmetric_ro( gates=gates_in_isa(device.get_isa())) qc = QuantumComputer( name="testy!", qam=QVM(connection=forest, noise_model=noise_model), device=device, compiler=DummyCompiler(), ) prog = Program(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 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_version(forest: ForestConnection): qvm = QVM(connection=forest) version_info = qvm.get_version_info() assert isinstance(version_info, dict) assert 'qvm-app' in version_info assert 'qvm-lib' in version_info def is_a_version_string(version_string: str): parts = version_string.split('.') try: map(int, parts) except ValueError: return False return True assert is_a_version_string(version_info['qvm-app']) assert is_a_version_string(version_info['qvm-lib'])
def test_run(forest): device = NxDevice(nx.complete_graph(3)) qc = QuantumComputer(name='testy!', qam=QVM(connection=forest, gate_noise=[0.01] * 3), device=device, compiler=DummyCompiler()) bitstrings = qc.run( Program(H(0), CNOT(0, 1), CNOT(1, 2), MEASURE(0, 0), MEASURE(1, 1), MEASURE(2, 2)).wrap_in_numshots_loop(1000)) assert bitstrings.shape == (1000, 3) parity = np.sum(bitstrings, axis=1) % 3 assert 0 < np.mean(parity) < 0.15
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_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_qc_expectation_larger_lattice(forest): device = NxDevice(nx.complete_graph(4)) qc = QuantumComputer(name='testy!', qam=QVM(connection=forest), device=device, compiler=DummyCompiler()) q0 = 2 q1 = 3 # bell state program p = Program() p += RESET() p += H(q0) p += CNOT(q0, q1) p.wrap_in_numshots_loop(10) # XX, YY, ZZ experiment sx = ExperimentSetting(in_state=sZ(q0) * sZ(q1), out_operator=sX(q0) * sX(q1)) sy = ExperimentSetting(in_state=sZ(q0) * sZ(q1), out_operator=sY(q0) * sY(q1)) sz = ExperimentSetting(in_state=sZ(q0) * sZ(q1), out_operator=sZ(q0) * sZ(q1)) e = TomographyExperiment(settings=[sx, sy, sz], program=p) results = qc.experiment(e) # XX expectation value for bell state |00> + |11> is 1 assert np.isclose(results[0].expectation, 1) assert np.isclose(results[0].std_err, 0) assert results[0].total_counts == 40 # YY expectation value for bell state |00> + |11> is -1 assert np.isclose(results[1].expectation, -1) assert np.isclose(results[1].std_err, 0) assert results[1].total_counts == 40 # ZZ expectation value for bell state |00> + |11> is 1 assert np.isclose(results[2].expectation, 1) assert np.isclose(results[2].std_err, 0) assert results[2].total_counts == 40
def test_run(forest): qc = QuantumComputer( name='testy!', qam=QVM(connection=forest, gate_noise=[0.01] * 3), device=NxDevice(nx.complete_graph(3)), ) bitstrings = qc.run(Program( H(0), CNOT(0, 1), CNOT(1, 2), MEASURE(0, 0), MEASURE(1, 1), MEASURE(2, 2), ), classical_addresses=[0, 1, 2], trials=1000) assert bitstrings.shape == (1000, 3) parity = np.sum(bitstrings, axis=1) % 3 assert 0 < np.mean(parity) < 0.15
def test_readout_symmetrization(forest): device = NxDevice(nx.complete_graph(3)) noise_model = decoherance_noise_with_asymmetric_ro(device.get_isa()) qc = QuantumComputer(name='testy!', qam=QVM(connection=forest, noise_model=noise_model), device=device) prog = Program(I(0), X(1), MEASURE(0, 0), MEASURE(1, 1)) bs1 = qc.run(prog, [0, 1], 1000) avg0_us = np.mean(bs1[:, 0]) avg1_us = 1 - np.mean(bs1[:, 1]) diff_us = avg1_us - avg0_us assert diff_us > 0.03 bs2 = qc.run_symmetrized_readout(prog, [0, 1], 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_qc_expectation_on_qvm_that_requires_executable(forest): # regression test for https://github.com/rigetti/forest-tutorials/issues/2 device = NxDevice(nx.complete_graph(2)) qc = QuantumComputer( name="testy!", qam=QVM(connection=forest, requires_executable=True), device=device, compiler=DummyCompiler(), ) p = Program() theta = p.declare("theta", "REAL") p += RESET() p += RY(theta, 0) p.wrap_in_numshots_loop(10000) sx = ExperimentSetting(in_state=sZ(0), out_operator=sX(0)) e = Experiment(settings=[sx], program=p) thetas = [-np.pi / 2, 0.0, np.pi / 2] results = [] # Verify that multiple calls to qc.experiment with the same experiment backed by a QVM that # requires_exectutable does not raise an exception. for theta in thetas: results.append(qc.experiment(e, memory_map={"theta": [theta]})) assert np.isclose(results[0][0].expectation, -1.0, atol=0.01) assert np.isclose(results[0][0].std_err, 0) assert results[0][0].total_counts == 20000 # bounds on atol and std_err here are a little loose to try and avoid test flakiness. assert np.isclose(results[1][0].expectation, 0.0, atol=0.1) assert results[1][0].std_err < 0.01 assert results[1][0].total_counts == 20000 assert np.isclose(results[2][0].expectation, 1.0, atol=0.01) assert np.isclose(results[2][0].std_err, 0) assert results[2][0].total_counts == 20000
topology = nx.from_edgelist([ (10, 2), (10, 4), (10, 6), (10, 8), ]) device = NxDevice(topology) class MyLazyCompiler(AbstractCompiler): def quil_to_native_quil(self, program, *, protoquil=None): return program def native_quil_to_executable(self, nq_program): return nq_program my_qc = QuantumComputer( name='my-qvm', qam=QVM(connection=ForestConnection()), device=device, compiler=MyLazyCompiler(), ) nx.draw(my_qc.qubit_topology()) plt.title('5qcm', fontsize=18) plt.show() my_qc.run_and_measure(Program(X(10)), trials=5)
def test_qvm_run_only_pqer(forest: ForestConnection): qvm = QVM(connection=forest, gate_noise=[0.01] * 3, requires_executable=True) p = Program(Declare("ro", "BIT"), X(0), MEASURE(0, MemoryReference("ro"))) p.wrap_in_numshots_loop(1000) with pytest.raises(TypeError) as e: qvm.load(p) qvm.run() qvm.wait() assert e.match(r".*Make sure you have explicitly compiled your program.*") nq = PyQuilExecutableResponse(program=p.out(), attributes={"num_shots": 1000}) qvm.load(nq) qvm.run() qvm.wait() bitstrings = qvm.read_memory(region_name="ro") assert bitstrings.shape == (1000, 1) assert np.mean(bitstrings) > 0.8
def test_qvm_run_region_not_declared_not_measured_non_ro(forest: ForestConnection): qvm = QVM(connection=forest) p = Program(X(0)) nq = PyQuilExecutableResponse(program=p.out(), attributes={"num_shots": 100}) qvm.load(nq).run().wait() assert qvm.read_memory(region_name="reg") is None
def test_qvm_run_region_not_declared_not_measured( client_configuration: QCSClientConfiguration): qvm = QVM(client_configuration=client_configuration) p = Program(X(0)) result = qvm.run(p.wrap_in_numshots_loop(100)) assert result.readout_data.get("ro") is None
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"))) result = qvm.run(p.wrap_in_numshots_loop(1000)) bitstrings = result.readout_data.get("ro") assert bitstrings.shape == (1000, 1)
def get_qc(name: str, *, as_qvm: bool = None, noisy: bool = None, connection: ForestConnection = None): """ Get a quantum computer. A quantum computer is an object of type :py:class:`QuantumComputer` and can be backed either by a QVM simulator ("Quantum/Quil Virtual Machine") or a physical Rigetti QPU ("Quantum Processing Unit") made of superconducting qubits. You can choose the quantum computer to target through a combination of its name and optional flags. There are multiple ways to get the same quantum computer. The following are equivalent:: >>> qc = get_qc("8Q-Agave-noisy-qvm") >>> qc = get_qc("8Q-Agave", as_qvm=True, noisy=True) and will construct a simulator of the 8q-agave chip with a noise model based on device characteristics. We also provide a means for constructing generic quantum simulators that are not related to a given piece of Rigetti hardware:: >>> qc = get_qc("9q-generic-qvm") >>> qc = get_qc("9q-generic", as_qvm=True) Redundant flags are acceptable, but conflicting flags will raise an exception:: >>> qc = get_qc("9q-generic-qvm") # qc is fully specified by its name >>> qc = get_qc("9q-generic-qvm", as_qvm=True) # redundant, but ok >>> qc = get_qc("9q-generic-qvm", as_qvm=False) # Error! Use :py:func:`list_quantum_computers` to retrieve a list of known qc names. This method is provided as a convenience to quickly construct and use QVM's and QPU's. Power users may wish to have more control over the specification of a quantum computer (e.g. custom noise models, bespoke topologies, etc.). This is possible by constructing a :py:class:`QuantumComputer` object by hand. Please refer to the documentation on :py:class:`QuantumComputer` for more information. :param name: The name of the desired quantum computer. This should correspond to a name returned by :py:func:`list_quantum_computers`. Names ending in "-qvm" will return a QVM. Names ending in "-noisy-qvm" will return a QVM with a noise model. Otherwise, we will return a QPU with the given name. :param as_qvm: An optional flag to force construction of a QVM (instead of a QPU). If specified and set to ``True``, a QVM-backed quantum computer will be returned regardless of the name's suffix :param noisy: An optional flag to force inclusion of a noise model. If specified and set to ``True``, a quantum computer with a noise model will be returned regardless of the name's suffix. The noise model for QVM's based on a real QPU is an empirically parameterized model based on real device noise characteristics. The generic QVM noise model is simple T1 and T2 noise plus readout error. See :py:func:`decoherance_noise_with_asymmetric_ro`. :param connection: An optional :py:class:ForestConnection` object. If not specified, the default values for URL endpoints, ping time, and status time will be used. Your user id and API key will be read from ~/.pyquil_config. If you deign to change any of these parameters, pass your own :py:class:`ForestConnection` object. :return: """ if connection is None: connection = ForestConnection() name, as_qvm, noisy = _parse_name(name, as_qvm, noisy) if name == '9q-generic': if not as_qvm: raise ValueError( "The device '9q-generic' is only available as a QVM") nineq_square = nx.convert_node_labels_to_integers( nx.grid_2d_graph(3, 3)) nineq_device = NxDevice(topology=nineq_square) if noisy: noise_model = decoherance_noise_with_asymmetric_ro( nineq_device.get_isa()) else: noise_model = None return QuantumComputer(name='9q-generic-qvm', qam=QVM(connection=connection, noise_model=noise_model), device=nineq_device) # At least based off a real device. device = get_devices(as_dict=True)[name] if not as_qvm: if noisy is not None and noisy: warnings.warn( "You have specified `noisy=True`, but you're getting a QPU. This flag " "is meant for controling noise models on QVMs.") return QuantumComputer(name=name, qam=QPU(device_name=name, connection=connection), device=device) if noisy: noise_model = device.noise_model name = "{name}-noisy-qvm".format(name=name) else: noise_model = None name = "{name}-qvm".format(name=name) return QuantumComputer(name=name, qam=QVM(connection=connection, noise_model=noise_model), device=device)