示例#1
0
    def status(self):
        """Query the API to update the status.

        Returns:
            JobStatus: The status of the job, once updated.

        Raises:
            JobError: if there was an exception in the future being executed
                          or the server sent an unknown answer.
        """

        # Implies self._job_id is None
        if self._future_captured_exception is not None:
            raise JobError(str(self._future_captured_exception))

        if self._job_id is None or self._status in JOB_FINAL_STATES:
            return self._status

        try:
            # TODO: See result values
            api_job = self._api.get_status_job(self._job_id)
            if 'status' not in api_job:
                raise JobError('get_status_job didn\'t return status: %s' %
                               pprint.pformat(api_job))
        # pylint: disable=broad-except
        except Exception as err:
            raise JobError(str(err))

        if api_job['status'] == 'VALIDATING':
            self._status = JobStatus.VALIDATING

        elif api_job['status'] == 'RUNNING':
            self._status = JobStatus.RUNNING
            queued, self._queue_position = _is_job_queued(api_job)
            if queued:
                self._status = JobStatus.QUEUED

        elif api_job['status'] == 'COMPLETED':
            self._status = JobStatus.DONE

        elif api_job['status'] == 'CANCELLED':
            self._status = JobStatus.CANCELLED
            self._cancelled = True

        elif 'ERROR' in api_job['status']:
            # Error status are of the form "ERROR_*_JOB"
            self._status = JobStatus.ERROR
            # TODO: This seems to be an inconsistency in the API package.
            self._api_error_msg = api_job.get('error') or api_job.get('Error')

        else:
            raise JobError('Unrecognized answer from server: \n{}'
                           .format(pprint.pformat(api_job)))

        return self._status
示例#2
0
    def _wait_for_result(self, timeout=None, wait=5):
        self._wait_for_submission()

        try:
            job_response = self._wait_for_job(timeout=timeout, wait=wait)
        except ApiError as api_err:
            raise JobError(str(api_err))

        status = self.status()
        if status is not JobStatus.DONE:
            raise JobError('Invalid job state. The job should be DONE but '
                           'it is {}'.format(str(status)))

        return job_response
示例#3
0
    def _wait_for_job(self, timeout=60, wait=5):
        """Wait until all online ran circuits of a qobj are 'COMPLETED'.

        Args:
            timeout (float or None): seconds to wait for job. If None, wait
                indefinitely.
            wait (float): seconds between queries

        Returns:
            dict: A dict with the contents of the API request.

        Raises:
            JobTimeoutError: if the job does not return results before a specified timeout.
            JobError: if something wrong happened in some of the server API calls
        """
        start_time = time.time()
        while self.status() not in JOB_FINAL_STATES:
            elapsed_time = time.time() - start_time
            if timeout is not None and elapsed_time >= timeout:
                raise JobTimeoutError(
                    'Timeout while waiting for the job: {}'.format(self._job_id)
                )

            logger.info('status = %s (%d seconds)', self._status, elapsed_time)
            time.sleep(wait)

        if self._cancelled:
            raise JobError(
                'Job result impossible to retrieve. The job was cancelled.')

        return self._api.get_job(self._job_id)
示例#4
0
    def submit(self):
        """Submit job to IBM-Q.

        Raises:
            JobError: If we have already submitted the job.
        """
        # TODO: Validation against the schema should be done here and not
        # during initiliazation. Once done, we should document that the method
        # can raise QobjValidationError.
        if self._future is not None or self._id is not None:
            raise JobError("We have already submitted the job!")

        api_jobs = []
        circuits = self._job_data['circuits']
        for circuit in circuits:
            job = _create_api_job_from_circuit(circuit)
            api_jobs.append(job)

        hpc = self._job_data['hpc']
        seed = self._job_data['seed']
        shots = self._job_data['shots']
        max_credits = self._job_data['max_credits']

        hpc_camel_cased = _format_hpc_parameters(hpc)

        self._future = self._executor.submit(self._submit_callback, api_jobs,
                                             self._backend_name,
                                             hpc_camel_cased, seed, shots,
                                             max_credits)
示例#5
0
    def submit(self):
        """Submit job to IBM-Q.

        Raises:
            JobError: If we have already submitted the job.
        """
        if self._future is not None or self._id is not None:
            raise JobError("We have already submitted the job!")

        api_jobs = []
        circuits = self._job_data['circuits']
        for circuit in circuits:
            job = _create_api_job_from_circuit(circuit)
            api_jobs.append(job)

        hpc = self._job_data['hpc']
        seed = self._job_data['seed']
        shots = self._job_data['shots']
        max_credits = self._job_data['max_credits']

        hpc_camel_cased = _format_hpc_parameters(hpc)

        self._future = self._executor.submit(self._submit_callback, api_jobs,
                                             self._backend_name,
                                             hpc_camel_cased, seed, shots,
                                             max_credits)
示例#6
0
    def _wait_for_submission(self, timeout=60):
        """Waits for the request to return a job ID"""
        if self._id is None:
            if self._future is None:
                raise JobError(
                    "You have to submit before asking for status or results!")
            try:
                submit_info = self._future.result(timeout=timeout)
            except TimeoutError as ex:
                raise JobTimeoutError(
                    "Timeout waiting for the job being submitted: {}".format(
                        ex))

            if 'error' in submit_info:
                self._status = JobStatus.ERROR
                self._api_error_msg = str(submit_info['error'])
                raise JobError(str(submit_info['error']))
示例#7
0
 def _wait_for_submission(self, timeout=60):
     """Waits for the request to return a job ID"""
     if self._job_id is None:
         if self._future is None:
             raise JobError("You have to submit before asking for status or results!")
         try:
             submit_info = self._future.result(timeout=timeout)
             if self._future_captured_exception is not None:
                 # pylint can't see if catch of None type
                 # pylint: disable=raising-bad-type
                 raise self._future_captured_exception
         except TimeoutError as ex:
             raise JobTimeoutError(
                 "Timeout waiting for the job being submitted: {}".format(ex)
             )
         if 'error' in submit_info:
             self._status = JobStatus.ERROR
             self._api_error_msg = str(submit_info['error'])
             raise JobError(str(submit_info['error']))
示例#8
0
    def submit(self):
        """Submit job to IBM-Q.

        Raises:
            JobError: If we have already submitted the job.
        """
        # TODO: Validation against the schema should be done here and not
        # during initiliazation. Once done, we should document that the method
        # can raise QobjValidationError.
        if self._future is not None or self._job_id is not None:
            raise JobError("We have already submitted the job!")
        self._future = self._executor.submit(self._submit_callback)
示例#9
0
    def submit(self):
        """Submit the job to the backend for execution.

        Raises:
            QobjValidationError: if the JSON serialization of the Qobj passed
            during construction does not validate against the Qobj schema.

            JobError: if trying to re-submit the job.
        """
        if self._future is not None:
            raise JobError("We have already submitted the job!")

        validate_qobj_against_schema(self._qobj)
        self._future = self._executor.submit(self._fn, self._qobj)
示例#10
0
    def result(self, timeout=None, wait=5):
        """Return the result from the job.

        Args:
           timeout (int): number of seconds to wait for job
           wait (int): time between queries to IBM Q server

        Returns:
            Result: Result object

        Raises:
            JobError: exception raised during job initialization
        """
        self._wait_for_submission()
        try:
            job_data = self._wait_for_job(timeout=timeout, wait=wait)
        except ApiError as api_err:
            raise JobError(str(api_err))

        if self._is_device and self.status() == JobStatus.DONE:
            _reorder_bits(job_data)

        # Build the Result.
        job_result_list = []
        for circuit_result in job_data['qasms']:
            this_result = {
                'data': circuit_result['data'],
                'name': circuit_result.get('name'),
                'compiled_circuit_qasm': circuit_result.get('qasm'),
                'status': circuit_result['status'],
                'success': circuit_result['status'] == 'DONE',
                'shots': job_data['shots']
            }
            if 'metadata' in circuit_result:
                this_result['metadata'] = circuit_result['metadata']

            job_result_list.append(this_result)

        return result_from_old_style_dict(
            {
                'id': self._id,
                'status': job_data['status'],
                'used_credits': job_data.get('usedCredits'),
                'result': job_result_list,
                'backend_name': self.backend_name(),
                'success': job_data['status'] == 'DONE'
            },
            [circuit_result['name'] for circuit_result in job_data['qasms']])
示例#11
0
    def status(self):
        """Gets the status of the job by querying the Python's future

        Returns:
            JobStatus: The current JobStatus

        Raises:
            JobError: If the future is in unexpected state
            concurrent.futures.TimeoutError: if timeout occurred.
        """
        # The order is important here
        if self._future.running():
            _status = JobStatus.RUNNING
        elif self._future.cancelled():
            _status = JobStatus.CANCELLED
        elif self._future.done():
            _status = JobStatus.DONE if self._future.exception() is None else JobStatus.ERROR
        else:
            raise JobError('Unexpected behavior of {0}'.format(
                self.__class__.__name__))
        return _status
示例#12
0
    def cancel(self):
        """Attempt to cancel a job.

        Returns:
            bool: True if job can be cancelled, else False. Currently this is
            only possible on commercial systems.

        Raises:
            JobError: if there was some unexpected failure in the server
        """
        hub = self._api.config.get('hub', None)
        group = self._api.config.get('group', None)
        project = self._api.config.get('project', None)

        try:
            response = self._api.cancel_job(self._job_id, hub, group, project)
            self._cancelled = 'error' not in response
            return self._cancelled
        except ApiError as error:
            self._cancelled = False
            raise JobError('Error cancelling job: %s' % error.usr_msg)
示例#13
0
    def result(self, timeout=None, wait=5):
        """Return the result from the job.

        Args:
           timeout (int): number of seconds to wait for job
           wait (int): time between queries to IBM Q server

        Returns:
            Result: Result object

        Raises:
            JobError: exception raised during job initialization
        """
        self._wait_for_submission()
        try:
            this_result = self._wait_for_job(timeout=timeout, wait=wait)
        except ApiError as api_err:
            raise JobError(str(api_err))

        if self._is_device and self.status() == JobStatus.DONE:
            _reorder_bits(this_result)

        return this_result
示例#14
0
    def submit(self):
        """Submit the job to the backend for running """
        if self._future is not None:
            raise JobError("We have already submitted the job!")

        self._future = self._executor.submit(self._fn, self._qobj)
示例#15
0
 def _wrapper(self, *args, **kwargs):
     if self._future is None:
         raise JobError("Job not submitted yet!. You have to .submit() first!")
     return func(self, *args, **kwargs)
示例#16
0
def _reorder_bits(job_data):
    """Temporary fix for ibmq backends.

    For every ran circuit, get reordering information from qobj
    and apply reordering on result.

    Args:
        job_data (dict): dict with the bare contents of the API.get_job request.

    Raises:
            JobError: raised if the creg sizes don't add up in result header.
    """
    for circuit_result in job_data['qasms']:
        if 'metadata' in circuit_result:
            circ = circuit_result['metadata'].get('compiled_circuit')
        else:
            logger.warning('result object missing metadata for reordering'
                           ' bits: bits may be out of order')
            return
        # device_qubit -> device_clbit (how it should have been)
        measure_dict = {op['qubits'][0]: op['clbits'][0]
                        for op in circ['operations']
                        if op['name'] == 'measure'}
        counts_dict_new = {}
        for item in circuit_result['data']['counts'].items():
            # fix clbit ordering to what it should have been
            bits = list(item[0])
            bits.reverse()  # lsb in 0th position
            count = item[1]
            reordered_bits = list('x' * len(bits))
            for device_clbit, bit in enumerate(bits):
                if device_clbit in measure_dict:
                    correct_device_clbit = measure_dict[device_clbit]
                    reordered_bits[correct_device_clbit] = bit
            reordered_bits.reverse()

            # only keep the clbits specified by circuit, not everything on device
            num_clbits = circ['header']['number_of_clbits']
            compact_key = reordered_bits[-num_clbits:]
            compact_key = "".join([b if b != 'x' else '0'
                                   for b in compact_key])

            # insert spaces to signify different classical registers
            cregs = circ['header']['clbit_labels']
            if sum([creg[1] for creg in cregs]) != num_clbits:
                raise JobError("creg sizes don't add up in result header.")
            creg_begin_pos = []
            creg_end_pos = []
            acc = 0
            for creg in reversed(cregs):
                creg_size = creg[1]
                creg_begin_pos.append(acc)
                creg_end_pos.append(acc + creg_size)
                acc += creg_size
            compact_key = " ".join([compact_key[creg_begin_pos[i]:creg_end_pos[i]]
                                    for i in range(len(cregs))])

            # marginalize over unwanted measured qubits
            if compact_key not in counts_dict_new:
                counts_dict_new[compact_key] = count
            else:
                counts_dict_new[compact_key] += count

        circuit_result['data']['counts'] = counts_dict_new