def result(self): """ The result of the job if available throws ValueError is result is not available yet throws ApiError if server returned an error indicating program execution was not successful or if the job was cancelled """ if not self.is_done(): raise ValueError( "Cannot get a result for a program that isn't completed.") if self._raw['status'] == 'CANCELLED': raise CancellationError(self._raw['result']) elif self._raw['status'] == 'ERROR': if self._machine == 'QVM': raise QVMError(self._raw['result']) elif self._machine == 'QPU': raise QPUError(self._raw['result']) elif self._machine == 'QUILC': raise QUILCError(self._raw['result']) else: raise UnknownApiError(self._raw['result']) if self._raw['program']['type'] == 'wavefunction': return Wavefunction.from_bit_packed_string( base64.b64decode(self._raw['result']), self._raw['program']['addresses']) elif self._raw['program']['type'] in [ 'multishot', 'multishot-measure', 'expectation' ]: return np.asarray(self._raw['result']) else: return self._raw['result']
def wavefunction( self, quil_program: Program, memory_map: Optional[Dict[str, List[Union[int, float]]]] = None ) -> Wavefunction: """ Simulate a Quil program and return the wavefunction. .. note:: If your program contains measurements or noisy gates, this method may not do what you want. If the execution of ``quil_program`` is **non-deterministic** then the final wavefunction only represents a stochastically generated sample and the wavefunctions returned by *different* ``wavefunction`` calls *will generally be different*. :param quil_program: A Quil program. :param memory_map: An assignment of classical registers to values, representing an initial state for the QAM's classical memory. This is expected to be of type Dict[str, List[Union[int, float]]], where the keys are memory region names and the values are arrays of initialization data. :return: A Wavefunction object representing the state of the QVM. """ if memory_map is not None: quil_program = self.augment_program_with_memory_values( quil_program, memory_map) request = self._wavefunction_request(quil_program=quil_program) response = self._qvm_client.get_wavefunction(request) return Wavefunction.from_bit_packed_string(response.wavefunction)
def result(self): """ The result of the job if available throws ValueError is result is not available yet throws ApiError if server returned an error indicating program execution was not successful or if the job was cancelled """ if not self.is_done(): raise ValueError( "Cannot get a result for a program that isn't completed.") if self._raw["status"] == "CANCELLED": raise CancellationError(self._raw["result"]) elif self._raw["status"] == "ERROR": if self._machine == "QVM": raise QVMError(self._raw["result"]) elif self._machine == "QPU": raise QPUError(self._raw["result"]) elif self._machine == "QUILC": raise QUILCError(self._raw["result"]) else: raise UnknownApiError(self._raw["result"]) if self._raw["program"]["type"] == "wavefunction": return Wavefunction.from_bit_packed_string( base64.b64decode(self._raw["result"]), self._raw["program"]["addresses"]) elif self._raw["program"]["type"] in [ "multishot", "multishot-measure", "expectation" ]: return np.asarray(self._raw["result"]) else: return self._raw["result"]
def wavefunction(self, quil_program, classical_addresses=None): """ Simulate a Quil program and get the wavefunction back. :note: If the execution of ``quil_program`` is **non-deterministic**, i.e., if it includes measurements and/or noisy quantum gates, then the final wavefunction from which the returned bitstrings are sampled itself only represents a stochastically generated sample and the wavefunctions returned by *different* ``wavefunction`` calls *will generally be different*. :param Program quil_program: A Quil program. :param list|range classical_addresses: An optional list of classical addresses. :return: A tuple whose first element is a Wavefunction object, and whose second element is the list of classical bits corresponding to the classical addresses. :rtype: Wavefunction """ if classical_addresses is None: classical_addresses = [] if self.use_queue: payload = self._wavefunction_payload(quil_program, classical_addresses) response = self._post_json(self.async_endpoint + "/job", { "machine": "QVM", "program": payload }) job = self.wait_for_job(get_job_id(response)) return job.result() else: payload = self._wavefunction_payload(quil_program, classical_addresses) response = self._post_json(self.sync_endpoint + "/qvm", payload) return Wavefunction.from_bit_packed_string(response.content, classical_addresses)
def wavefunction(self, quil_program, classical_addresses=None, needs_compilation=False, isa=None): """ Simulate a Quil program and get the wavefunction back. :note: If the execution of ``quil_program`` is **non-deterministic**, i.e., if it includes measurements and/or noisy quantum gates, then the final wavefunction from which the returned bitstrings are sampled itself only represents a stochastically generated sample and the wavefunctions returned by *different* ``wavefunction`` calls *will generally be different*. :param Program quil_program: A Quil program. :param list|range classical_addresses: An optional list of classical addresses. :param needs_compilation: If True, preprocesses the job with the compiler. :param isa: If set, compiles to this target ISA. :return: A Wavefunction object representing the state of the QVM. :rtype: Wavefunction """ if classical_addresses is None: classical_addresses = [] if self.use_queue or needs_compilation: if needs_compilation and not self.use_queue: warnings.warn('Synchronous QVM connection does not support compilation preprocessing. Running this job over the asynchronous endpoint, as if use_queue were set to True.') payload = self._wavefunction_payload(quil_program, classical_addresses, needs_compilation, isa) response = post_json(self.session, self.async_endpoint + "/job", {"machine": "QVM", "program": payload}) job = self.wait_for_job(get_job_id(response)) return job.result() else: payload = self._wavefunction_payload(quil_program, classical_addresses, needs_compilation, isa) response = post_json(self.session, self.sync_endpoint + "/qvm", payload) return Wavefunction.from_bit_packed_string(response.content, classical_addresses)
def _wavefunction(self, quil_program, random_seed) -> Wavefunction: """ Run a Forest ``wavefunction`` job. Users should use :py:func:`WavefunctionSimulator.wavefunction` instead of calling this directly. """ payload = wavefunction_payload(quil_program, random_seed) response = post_json(self.session, self.sync_endpoint + "/qvm", payload) return Wavefunction.from_bit_packed_string(response.content)
def result(self): """ The result of the job if available, ValueError otherwise """ if not self.is_done(): raise ValueError( "Cannot get a result for a program that isn't completed.") if self.raw['program']['type'] == 'wavefunction': return Wavefunction.from_bit_packed_string( base64.b64decode(self.raw['result']), self.raw['program']['addresses']) else: return self.raw['result']
def _wavefunction(self, quil_program, classical_addresses, random_seed) -> Wavefunction: """ Run a Forest ``wavefunction`` job. Users should use :py:func:`WavefunctionSimulator.wavefunction` instead of calling this directly. """ if self.use_queue: payload = wavefunction_payload(quil_program, classical_addresses, random_seed) response = post_json(self.session, self.async_endpoint + "/job", {"machine": "QVM", "program": payload}) job = self._wait_for_job(get_job_id(response), machine='QVM') return job.result() else: payload = wavefunction_payload(quil_program, classical_addresses, random_seed) response = post_json(self.session, self.sync_endpoint + "/qvm", payload) return Wavefunction.from_bit_packed_string(response.content, classical_addresses)
def result(self): """ The result of the job if available throws ValueError is result is not available yet throws RuntimeError if server returned an error indicating program execution was not successful or if the job was cancelled """ if not self.is_done(): raise ValueError("Cannot get a result for a program that isn't completed.") if self._raw['status'] == 'CANCELLED': raise RuntimeError("Job was cancelled: {}".format(self._raw['result'])) elif self._raw['status'] == 'ERROR': raise RuntimeError("Server returned an error: {}".format(self._raw['result'])) if self._raw['program']['type'] == 'wavefunction': return Wavefunction.from_bit_packed_string( base64.b64decode(self._raw['result']), self._raw['program']['addresses']) else: return self._raw['result']
def wavefunction(self, quil_program): """ Simulate a Quil program and get the wavefunction back. :note: If the execution of ``quil_program`` is **non-deterministic**, i.e., if it includes measurements and/or noisy quantum gates, then the final wavefunction from which the returned bitstrings are sampled itself only represents a stochastically generated sample and the wavefunctions returned by *different* ``wavefunction`` calls *will generally be different*. :param Program quil_program: A Quil program. :return: A Wavefunction object representing the state of the QVM. :rtype: Wavefunction """ # Developer note: This code is for backwards compatibility. It can't be replaced with # ForestConnection._wavefunction because we've turned off the ability to set # `needs_compilation` (that usually indicates the user is doing something iffy like # using a noise model with this function) payload = self._wavefunction_payload(quil_program) response = post_json(self.session, self.sync_endpoint + "/qvm", payload) return Wavefunction.from_bit_packed_string(response.content)