def forest(): try: connection = ForestConnection() connection._wavefunction(Program(I(0)), 52) return connection except (RequestException, UnknownApiError) as e: return pytest.skip("This test requires a Forest connection: {}".format(e))
def test_expectation_async(forest: ForestConnection): # This tests the private _expectation_async method. # Users shouldn't use this, but lets make sure we're returning the right data type bell = Program( H(0), CNOT(0, 1), ) job_id = forest._expectation_async( bell, [Program(X(0)), Program(X(1))], random_seed=52) job = forest._wait_for_job(job_id, machine='QVM') raw_coefs = job.result() assert raw_coefs.shape == (2, )
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 list_quantum_computers(connection: ForestConnection = None, qpus=True, qvms=True) -> List[str]: """ List the names of available quantum computers :param connection: An optional :py:class:ForestConnection` object. If not specified, the default values for URL endpoints will be used, and your API key will be read from ~/.pyquil_config. If you deign to change any of these parameters, pass your own :py:class:`ForestConnection` object. :param qpus: Whether to include QPU's in the list. :param qvms: Whether to include QVM's in the list. """ if connection is None: # TODO: Use this to list devices? connection = ForestConnection() qc_names = [] if qpus: for qpu_name in ['8Q-Agave', '19Q-Acorn']: qc_names += [qpu_name] if qvms: qc_names += [ "{}-qvm".format(qpu_name), "{}-noisy-qvm".format(qpu_name) ] if qvms: qc_names += ['9q-generic-qvm', '9q-generic-noisy-qvm'] return qc_names
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 init_qvm_and_quilc(qvm_executable="qvm", quilc_executable="quilc"): qvm_port = get_free_port() quilc_port = get_free_port() qvm_server = subprocess.Popen([qvm_executable, "-S", "-p", str(qvm_port)]) quilc_server = subprocess.Popen([quilc_executable, "-S", "-p", str(quilc_port)]) fc = ForestConnection(sync_endpoint='http://127.0.0.1:' + str(qvm_port), compiler_endpoint='http://127.0.0.1:' + str(quilc_port)) return qvm_server, quilc_server, fc
def init_qvm_and_quilc(qvm_executable="qvm", quilc_executable="quilc"): qvm_port = get_free_port() quilc_port = get_free_port() qvm_server = subprocess.Popen([qvm_executable, "-S", "-p", str(qvm_port)]) quilc_server = subprocess.Popen([quilc_executable, "-R", "-p", str(quilc_port)]) fc = ForestConnection(sync_endpoint='http://127.0.0.1:' + str(qvm_port), compiler_endpoint='tcp://127.0.0.1:' + str(quilc_port)) time.sleep(1) #Temporary solution to prevent notebook racing ahead of server initilisation return qvm_server, quilc_server, fc
def get_backend(provider, qpu): """ Get the backend instance by name :param provider: :param qpu: :return: """ if provider.lower() == "ibmq": try: return IBMQBackend(qpu) except NoIBMQAccountError: return None if provider.lower() == "rigetti": # Create a connection to the forest SDK connection = ForestConnection( sync_endpoint=f"http://{qvm_hostname}:{qvm_port}", compiler_endpoint=f"tcp://{quilc_hostname}:{quilc_port}") return ForestBackend(qpu, simulator=True, connection=connection) # Default if no provider matched return None
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 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)