Example #1
0
 def run_with_api(self, api):
     """Creates a new ``IBMQJob`` running with the provided API object."""
     backend = FakeRueschlikon()
     self._current_api = api
     self._current_qjob = IBMQJob(backend, None, api, qobj=new_fake_qobj())
     self._current_qjob.submit()
     return self._current_qjob
Example #2
0
def run_on_backend(backend,
                   qobj,
                   backend_options=None,
                   noise_config=None,
                   skip_qobj_validation=False):
    if skip_qobj_validation:
        job_id = str(uuid.uuid4())
        if is_aer_provider(backend):
            from qiskit.providers.aer.aerjob import AerJob
            temp_backend_options = backend_options[
                'backend_options'] if backend_options != {} else None
            temp_noise_config = noise_config[
                'noise_model'] if noise_config != {} else None
            job = AerJob(backend, job_id, backend._run_job, qobj,
                         temp_backend_options, temp_noise_config, False)
            job._future = job._executor.submit(job._fn, job._job_id, job._qobj,
                                               *job._args)
        elif is_basicaer_provider(backend):
            backend._set_options(qobj_config=qobj.config, **backend_options)
            job = BasicAerJob(backend, job_id, backend._run_job, qobj)
            job._future = job._executor.submit(job._fn, job._job_id, job._qobj)
        elif is_ibmq_provider(backend):
            # TODO: IBMQJob performs validation during the constructor. the following lines does not
            # skip validation but run as is.
            from qiskit.providers.ibmq.ibmqjob import IBMQJob
            job = IBMQJob(backend, None, backend._api, qobj=qobj)
            job._future = job._executor.submit(job._submit_callback)
        else:
            logger.info(
                "Can't skip qobj validation for the third-party provider.")
            job = backend.run(qobj, **backend_options, **noise_config)
        return job
    else:
        job = backend.run(qobj, **backend_options, **noise_config)
        return job
Example #3
0
def run_on_backend(backend,
                   qobj,
                   backend_options=None,
                   noise_config=None,
                   skip_qobj_validation=False):
    if skip_qobj_validation:
        job_id = str(uuid.uuid4())
        if is_simulator_backend(backend):
            if is_aer_provider(backend):
                job = backend.run(qobj, **backend_options, **noise_config)
            else:
                job = SimulatorsJob(backend, job_id, backend._run_job, qobj)
                job._future = job._executor.submit(job._fn, job._job_id,
                                                   job._qobj)
        elif is_ibmq_provider(backend):
            job = IBMQJob(backend,
                          None,
                          backend._api,
                          not is_simulator_backend(backend),
                          qobj=qobj)
            job._future = job._executor.submit(job._fn, job._job_id, job._qobj)
        else:
            logger.info(
                "Can not skip qobj validation for the third-party provider.")
            job = backend.run(qobj, **backend_options, **noise_config)
        return job
    else:
        job = backend.run(qobj, **backend_options, **noise_config)
        return job
Example #4
0
def run_on_backend(backend,
                   qobj,
                   backend_options=None,
                   noise_config=None,
                   skip_qobj_validation=False):
    if skip_qobj_validation:
        job_id = str(uuid.uuid4())
        if backend.configuration().simulator:
            if type(backend.provider()).__name__ == 'AerProvider':
                from qiskit.providers.aer.aerjob import AerJob
                job = AerJob(backend, job_id, backend._run_job, qobj,
                             backend_options, noise_config)
                job._future = job._executor.submit(job._fn, job._job_id,
                                                   job._qobj, backend_options,
                                                   noise_config)
            else:
                job = SimulatorsJob(backend, job_id, backend._run_job, qobj)
                job._future = job._executor.submit(job._fn, job._job_id,
                                                   job._qobj)
        else:
            job = IBMQJob(backend,
                          None,
                          backend._api,
                          not backend.configuration().simulator,
                          qobj=qobj)
            job._future = job._executor.submit(job._fn, job._job_id, job._qobj)
        return job
    else:
        job = backend.run(qobj, **backend_options, **noise_config)
        return job
Example #5
0
    def _call_circuit(self, name, **kwargs):
        """Execute a Circuit.

        Args:
            name (str): name of the Circuit.
            **kwargs: parameters passed to the Circuit.

        Returns:
            Result: the result of executing the circuit.

        Raises:
            CircuitAvailabilityError: if Circuits are not available.
            CircuitSubmitError: if there was an error submitting the Circuit.
            CircuitResultError: if the result of the Circuit could not be
                returned.
        """
        try:
            response = self.client.circuit_run(name=name, **kwargs)
        except RequestsApiError as ex:
            # Revise the original requests exception to intercept.
            response = ex.original_exception.response

            # Check for errors related to the submission.
            try:
                body = response.json()
            except ValueError:
                body = {}

            # Generic authorization or unavailable endpoint error.
            if response.status_code in (401, 404):
                raise CircuitAvailabilityError() from None

            if response.status_code == 400:
                # Hub permission error.
                if body.get('error', {}).get('code') == 'HUB_NOT_FOUND':
                    raise CircuitAvailabilityError() from None

                # Generic error.
                if body.get('error', {}).get('code') == 'GENERIC_ERROR':
                    raise CircuitAvailabilityError() from None

            # Handle the rest of the exceptions as unexpected.
            raise CircuitSubmitError(str(ex))
        except Exception as ex:
            # Handle non-requests exception as unexpected.
            raise CircuitSubmitError(str(ex))

        # Extra check for IBMQConnector code path.
        if 'error' in response:
            # Hub permission error.
            if response['error'].get('code') == 'HUB_NOT_FOUND':
                raise CircuitAvailabilityError() from None

            # Generic error.
            if response['error'].get('code') == 'GENERIC_ERROR':
                raise CircuitAvailabilityError() from None

            raise CircuitSubmitError(str(response))

        # Create a Job for the circuit.
        try:
            job = IBMQJob(backend=None,
                          job_id=response['id'],
                          api=self.client,
                          creation_date=response['creationDate'],
                          api_status=response['status'])
        except Exception as ex:
            raise CircuitResultError(str(ex))

        # Wait for the job to complete, explicitly checking for errors.
        job._wait_for_completion()
        if job.status() is JobStatus.ERROR:
            raise CircuitResultError('Job {} finished with an error'.format(
                job.job_id()))

        return job.result()
Example #6
0
class TestIBMQJobStates(JobTestCase):
    """Test the states of an IBMQJob."""
    def setUp(self):
        self._current_api = None
        self._current_qjob = None

    def test_unrecognized_status(self):
        job = self.run_with_api(UnknownStatusAPI())
        with self.assertRaises(JobError):
            self.wait_for_initialization(job)

    def test_validating_job(self):
        job = self.run_with_api(ValidatingAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.VALIDATING)

    def test_error_while_creating_job(self):
        job = self.run_with_api(ErrorWhileCreatingAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.ERROR)

    def test_error_while_validating_job(self):
        job = self.run_with_api(ErrorWhileValidatingAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.VALIDATING)

        self._current_api.progress()
        self.assertEqual(job.status(), JobStatus.ERROR)

    def test_status_flow_for_non_queued_job(self):
        job = self.run_with_api(NonQueuedAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.RUNNING)

        self._current_api.progress()
        self.assertEqual(job.status(), JobStatus.DONE)

    def test_status_flow_for_queued_job(self):
        job = self.run_with_api(QueuedAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.QUEUED)

        self._current_api.progress()
        self.assertEqual(job.status(), JobStatus.RUNNING)

        self._current_api.progress()
        self.assertEqual(job.status(), JobStatus.DONE)

    def test_status_flow_for_cancellable_job(self):
        job = self.run_with_api(CancellableAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.RUNNING)

        can_cancel = job.cancel()
        self.assertTrue(can_cancel)

        self._current_api.progress()
        self.assertEqual(job.status(), JobStatus.CANCELLED)

    def test_status_flow_for_non_cancellable_job(self):
        job = self.run_with_api(NonCancellableAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.RUNNING)

        can_cancel = job.cancel()
        self.assertFalse(can_cancel)

        self._current_api.progress()
        self.assertEqual(job.status(), JobStatus.RUNNING)

    def test_status_flow_for_errored_cancellation(self):
        job = self.run_with_api(ErroredCancellationAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.RUNNING)
        can_cancel = job.cancel()
        self.assertFalse(can_cancel)
        self.assertEqual(job.status(), JobStatus.RUNNING)

    def test_status_flow_for_unable_to_run_valid_qobj(self):
        """Contrary to other tests, this one is expected to fail even for a
        non-job-related issue. If the API fails while sending a job, we don't
        get an id so we can not query for the job status."""
        job = self.run_with_api(UnavailableRunAPI())

        with self.assertRaises(JobError):
            self.wait_for_initialization(job)

        with self.assertRaises(JobError):
            job.status()

    def test_api_throws_temporarily_but_job_is_finished(self):
        job = self.run_with_api(
            ThrowingNonJobRelatedErrorAPI(errors_before_success=2))

        # First time we query the server...
        with self.assertRaises(JobError):
            # The error happens inside wait_for_initialization, the first time
            # it calls to status() after INITIALIZING.
            self.wait_for_initialization(job)

        # Also an explicit second time...
        with self.assertRaises(JobError):
            job.status()

        # Now the API gets fixed and doesn't throw anymore.
        self.assertEqual(job.status(), JobStatus.DONE)

    def test_status_flow_for_unable_to_run_invalid_qobj(self):
        job = self.run_with_api(RejectingJobAPI())
        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.ERROR)

    def test_error_while_running_job(self):
        job = self.run_with_api(ErrorWhileRunningAPI())

        self.wait_for_initialization(job)
        self.assertEqual(job.status(), JobStatus.RUNNING)

        self._current_api.progress()
        self.assertEqual(job.status(), JobStatus.ERROR)
        self.assertIn('Error 1', job.error_message())
        self.assertIn('Error 2', job.error_message())

    def test_cancelled_result(self):
        job = self.run_with_api(CancellableAPI())

        self.wait_for_initialization(job)
        job.cancel()
        self._current_api.progress()
        with self.assertRaises(JobError):
            _ = job.result()
            self.assertEqual(job.status(), JobStatus.CANCELLED)

    def test_errored_result(self):
        job = self.run_with_api(ThrowingGetJobAPI())
        self.wait_for_initialization(job)
        with self.assertRaises(ApiError):
            job.result()

    def test_completed_result(self):
        job = self.run_with_api(NonQueuedAPI())

        self.wait_for_initialization(job)
        self._current_api.progress()
        self.assertEqual(job.result().success, True)
        self.assertEqual(job.status(), JobStatus.DONE)

    def test_block_on_result_waiting_until_completed(self):
        from concurrent import futures

        job = self.run_with_api(NonQueuedAPI())
        with futures.ThreadPoolExecutor() as executor:
            executor.submit(_auto_progress_api, self._current_api)

        result = job.result()
        self.assertEqual(result.success, True)
        self.assertEqual(job.status(), JobStatus.DONE)

    def test_block_on_result_waiting_until_cancelled(self):
        from concurrent.futures import ThreadPoolExecutor

        job = self.run_with_api(CancellableAPI())
        with ThreadPoolExecutor() as executor:
            executor.submit(_auto_progress_api, self._current_api)

        with self.assertRaises(JobError):
            job.result()

        self.assertEqual(job.status(), JobStatus.CANCELLED)

    def test_block_on_result_waiting_until_exception(self):
        from concurrent.futures import ThreadPoolExecutor
        job = self.run_with_api(ThrowingAPI())

        with ThreadPoolExecutor() as executor:
            executor.submit(_auto_progress_api, self._current_api)

        with self.assertRaises(JobError):
            job.result()

    def test_never_complete_result_with_timeout(self):
        job = self.run_with_api(NonQueuedAPI())

        self.wait_for_initialization(job)
        with self.assertRaises(JobTimeoutError):
            job.result(timeout=0.2)

    def test_cancel_while_initializing_fails(self):
        job = self.run_with_api(CancellableAPI())
        can_cancel = job.cancel()
        self.assertFalse(can_cancel)
        self.assertEqual(job.status(), JobStatus.INITIALIZING)

    def test_only_final_states_cause_detailed_request(self):
        from unittest import mock

        # The state ERROR_CREATING_JOB is only handled when running the job,
        # and not while checking the status, so it is not tested.
        all_state_apis = {
            'COMPLETED': NonQueuedAPI,
            'CANCELLED': CancellableAPI,
            'ERROR_VALIDATING_JOB': ErrorWhileValidatingAPI,
            'ERROR_RUNNING_JOB': ErrorWhileRunningAPI
        }

        for status, api in all_state_apis.items():
            with self.subTest(status=status):
                job = self.run_with_api(api())
                self.wait_for_initialization(job)

                with suppress(BaseFakeAPI.NoMoreStatesError):
                    self._current_api.progress()

                with mock.patch.object(self._current_api,
                                       'get_job',
                                       wraps=self._current_api.get_job):
                    job.status()
                    if ApiJobStatus(status) in API_JOB_FINAL_STATES:
                        self.assertTrue(self._current_api.get_job.called)
                    else:
                        self.assertFalse(self._current_api.get_job.called)

    def run_with_api(self, api):
        """Creates a new ``IBMQJob`` running with the provided API object."""
        backend = FakeRueschlikon()
        self._current_api = api
        self._current_qjob = IBMQJob(backend, None, api, qobj=new_fake_qobj())
        self._current_qjob.submit()
        return self._current_qjob