Exemplo n.º 1
0
    def execute(self, circuits):
        """
        A wrapper for all algorithms to interface with quantum backend.

        Args:
            circuits (QuantumCircuit or list[QuantumCircuit]): circuits to execute

        Returns:
            Result or [Result]: Result objects it will be a list if number of circuits
            exceed the maximum number (300)
        """

        if not isinstance(circuits, list):
            circuits = [circuits]
        jobs = []
        chunks = int(np.ceil(len(circuits) / self.MAX_CIRCUITS_PER_JOB))
        for i in range(chunks):
            sub_circuits = circuits[i * self.MAX_CIRCUITS_PER_JOB:(i + 1) *
                                    self.MAX_CIRCUITS_PER_JOB]
            jobs.append(
                q_execute(sub_circuits, self._backend, **self._execute_config))

        if logger.isEnabledFor(logging.DEBUG):
            logger.debug(summarize_circuits(circuits))

        results = []
        for job in jobs:
            results.append(job.result(**self._qjob_config))

        result = functools.reduce(lambda x, y: x + y, results)
        return result
Exemplo n.º 2
0
def run_circuits(circuits, backend, execute_config, qjob_config={},
                 show_circuit_summary=False, has_shared_circuits=False):
    """
    An execution wrapper with Qiskit-Terra, with job auto recover capability.

    The autorecovery feature is only applied for non-simulator backend.
    This wraper will try to get the result no matter how long it costs.

    Args:
        circuits (QuantumCircuit or list[QuantumCircuit]): circuits to execute
        backend (BaseBackend): backend instance
        execute_config (dict): settings for qiskit execute (or compile)
        qjob_config (dict): settings for job object, like timeout and wait
        show_circuit_summary (bool): showing the summary of submitted circuits.
        has_shared_circuits (bool): use the 0-th circuits as initial state for other circuits.
    Returns:
        Result: Result object

    Raises:
        AlgorithmError: Any error except for JobError raised by Qiskit Terra
    """
    if backend is None or not isinstance(backend, BaseBackend):
        raise AlgorithmError('Backend is missing or not an instance of BaseBackend')

    if not isinstance(circuits, list):
        circuits = [circuits]

    if backend.configuration().get('name', '').startswith('statevector'):
        circuits = _avoid_empty_circuits(circuits)

    if has_shared_circuits and version.parse(qiskit.__version__) > version.parse('0.6.1'):
        return _reuse_shared_circuits(circuits, backend, execute_config, qjob_config)

    with_autorecover = False if backend.configuration()['simulator'] else True
    max_circuits_per_job = sys.maxsize if backend.configuration()['local'] \
        else MAX_CIRCUITS_PER_JOB

    qobjs = []
    jobs = []
    chunks = int(np.ceil(len(circuits) / max_circuits_per_job))

    for i in range(chunks):
        sub_circuits = circuits[i *
                                max_circuits_per_job:(i + 1) * max_circuits_per_job]
        qobj = q_compile(sub_circuits, backend, **execute_config)
        job = backend.run(qobj)
        jobs.append(job)
        qobjs.append(qobj)

    if logger.isEnabledFor(logging.DEBUG) and show_circuit_summary:
        logger.debug(summarize_circuits(circuits))

    results = []
    if with_autorecover:

        logger.debug("There are {} circuits and they are chunked into {} chunks, "
                     "each with {} circutis.".format(len(circuits), chunks,
                                                     max_circuits_per_job))

        for idx in range(len(jobs)):
            job = jobs[idx]
            job_id = job.job_id()
            logger.info("Running {}-th chunk circuits, job id: {}".format(idx, job_id))
            while True:
                try:
                    result = job.result(**qjob_config)
                    if result.status == 'COMPLETED':
                        results.append(result)
                        logger.info("COMPLETED the {}-th chunk of circuits, "
                                    "job id: {}".format(idx, job_id))
                        break
                    else:
                        logger.warning("FAILURE: the {}-th chunk of circuits, "
                                       "job id: {}".format(idx, job_id))
                except JobError as e:
                    # if terra raise any error, which means something wrong, re-run it
                    logger.warning("FAILURE: the {}-th chunk of circuits, job id: {}, "
                                   "Terra job error: {} ".format(idx, job_id, e))
                except Exception as e:
                    raise AlgorithmError("FAILURE: the {}-th chunk of circuits, job id: {}, "
                                         "Terra unknown error: {} ".format(idx, job_id, e)) from e

                # keep querying the status until it is okay.
                while True:
                    try:
                        job_status = job.status()
                        break
                    except JobError as e:
                        logger.warning("FAILURE: job id: {}, "
                                       "status: 'FAIL_TO_GET_STATUS' "
                                       "Terra job error: {}".format(job_id, e))
                        time.sleep(5)
                    except Exception as e:
                        raise AlgorithmError("FAILURE: job id: {}, "
                                             "status: 'FAIL_TO_GET_STATUS' "
                                             "({})".format(job_id, e)) from e

                logger.info("Job status: {}".format(job_status))
                # when reach here, it means the job fails. let's check what kinds of failure it is.
                if job_status == JobStatus.DONE:
                    logger.info("Job ({}) is completed anyway, retrieve result "
                                "from backend.".format(job_id))
                    job = backend.retrieve_job(job_id)
                elif job_status == JobStatus.RUNNING or job_status == JobStatus.QUEUED:
                    logger.info("Job ({}) is {}, but encounter an exception, "
                                "recover it from backend.".format(job_id, job_status))
                    job = backend.retrieve_job(job_id)
                else:
                    logger.info("Fail to run Job ({}), resubmit it.".format(job_id))
                    qobj = qobjs[idx]
                    job = backend.run(qobj)
    else:
        results = []
        for job in jobs:
            results.append(job.result(**qjob_config))

    if len(results) != 0:
        result = functools.reduce(lambda x, y: x + y, results)
    else:
        result = None
    return result
Exemplo n.º 3
0
def compile_and_run_circuits(circuits,
                             backend,
                             backend_config,
                             compile_config,
                             run_config,
                             qjob_config=None,
                             backend_options=None,
                             noise_config=None,
                             show_circuit_summary=False,
                             has_shared_circuits=False):
    """
    An execution wrapper with Qiskit-Terra, with job auto recover capability.

    The autorecovery feature is only applied for non-simulator backend.
    This wraper will try to get the result no matter how long it costs.

    Args:
        circuits (QuantumCircuit or list[QuantumCircuit]): circuits to execute
        backend (BaseBackend): backend instance
        backend_config (dict): configuration for backend
        compile_config (dict): configuration for compilation
        run_config (dict): configuration for running a circuit
        qjob_config (dict): configuration for quantum job object
        backend_options (dict): configuration for simulator
        noise_config (dict): configuration for noise model
        show_circuit_summary (bool): showing the summary of submitted circuits.
        has_shared_circuits (bool): use the 0-th circuits as initial state for other circuits.

    Returns:
        Result: Result object

    Raises:
        AquaError: Any error except for JobError raised by Qiskit Terra
    """
    qjob_config = qjob_config or {}
    backend_options = backend_options or {}
    noise_config = noise_config or {}

    if backend is None or not isinstance(backend, BaseBackend):
        raise ValueError(
            'Backend is missing or not an instance of BaseBackend')

    if not isinstance(circuits, list):
        circuits = [circuits]

    if 'statevector' in backend.name():
        circuits = _avoid_empty_circuits(circuits)

    if has_shared_circuits:
        return _reuse_shared_circuits(circuits, backend, backend_config,
                                      compile_config, run_config, qjob_config,
                                      backend_options)

    with_autorecover = False if backend.configuration().simulator else True

    if MAX_CIRCUITS_PER_JOB is not None:
        max_circuits_per_job = int(MAX_CIRCUITS_PER_JOB)
    else:
        if backend.configuration().local:
            max_circuits_per_job = sys.maxsize
        else:
            max_circuits_per_job = backend.configuration().max_experiments

    qobjs = []
    jobs = []
    job_ids = []
    chunks = int(np.ceil(len(circuits) / max_circuits_per_job))
    for i in range(chunks):
        sub_circuits = circuits[i * max_circuits_per_job:(i + 1) *
                                max_circuits_per_job]
        qobj = q_compile(sub_circuits, backend, **backend_config,
                         **compile_config, **run_config)
        # assure get job ids
        while True:
            job = backend.run(qobj, **backend_options, **noise_config)
            try:
                job_id = job.job_id()
                break
            except JobError as e:
                logger.warning(
                    "FAILURE: the {}-th chunk of circuits, can not get job id, "
                    "Resubmit the qobj to get job id. "
                    "Terra job error: {} ".format(i, e))
            except Exception as e:
                logger.warning(
                    "FAILURE: the {}-th chunk of circuits, can not get job id, "
                    "Resubmit the qobj to get job id. "
                    "Error: {} ".format(i, e))
        job_ids.append(job_id)
        jobs.append(job)
        qobjs.append(qobj)

    if logger.isEnabledFor(logging.DEBUG) and show_circuit_summary:
        logger.debug(summarize_circuits(circuits))

    results = []
    if with_autorecover:
        logger.info("Backend status: {}".format(backend.status()))
        logger.info(
            "There are {} circuits and they are chunked into {} chunks, "
            "each with {} circutis (max.).".format(len(circuits), chunks,
                                                   max_circuits_per_job))
        logger.info("All job ids:\n{}".format(job_ids))
        for idx in range(len(jobs)):
            while True:
                job = jobs[idx]
                job_id = job_ids[idx]
                logger.info("Running {}-th chunk circuits, job id: {}".format(
                    idx, job_id))
                # try to get result if possible
                try:
                    result = job.result(**qjob_config)
                    if result.success:
                        results.append(result)
                        logger.info("COMPLETED the {}-th chunk of circuits, "
                                    "job id: {}".format(idx, job_id))
                        break
                    else:
                        logger.warning("FAILURE: the {}-th chunk of circuits, "
                                       "job id: {}".format(idx, job_id))
                except JobError as e:
                    # if terra raise any error, which means something wrong, re-run it
                    logger.warning(
                        "FAILURE: the {}-th chunk of circuits, job id: {} "
                        "Terra job error: {} ".format(idx, job_id, e))
                except Exception as e:
                    raise AquaError(
                        "FAILURE: the {}-th chunk of circuits, job id: {} "
                        "Unknown error: {} ".format(idx, job_id, e)) from e

                # something wrong here, querying the status to check how to handle it.
                # keep qeurying it until getting the status.
                while True:
                    try:
                        job_status = job.status()
                        break
                    except JobError as e:
                        logger.warning("FAILURE: job id: {}, "
                                       "status: 'FAIL_TO_GET_STATUS' "
                                       "Terra job error: {}".format(job_id, e))
                        time.sleep(5)
                    except Exception as e:
                        raise AquaError("FAILURE: job id: {}, "
                                        "status: 'FAIL_TO_GET_STATUS' "
                                        "Unknown error: ({})".format(
                                            job_id, e)) from e

                logger.info("Job status: {}".format(job_status))

                # handle the failure job based on job status
                if job_status == JobStatus.DONE:
                    logger.info(
                        "Job ({}) is completed anyway, retrieve result "
                        "from backend.".format(job_id))
                    job = backend.retrieve_job(job_id)
                elif job_status == JobStatus.RUNNING or job_status == JobStatus.QUEUED:
                    logger.info("Job ({}) is {}, but encounter an exception, "
                                "recover it from backend.".format(
                                    job_id, job_status))
                    job = backend.retrieve_job(job_id)
                else:
                    logger.info(
                        "Fail to run Job ({}), resubmit it.".format(job_id))
                    qobj = qobjs[idx]
                    #  assure job get its id
                    while True:
                        job = backend.run(qobj, **backend_options,
                                          **noise_config)
                        try:
                            job_id = job.job_id()
                            break
                        except JobError as e:
                            logger.warning(
                                "FAILURE: the {}-th chunk of circuits, "
                                "can not get job id. Resubmit the qobj to get job id. "
                                "Terra job error: {} ".format(idx, e))
                        except Exception as e:
                            logger.warning(
                                "FAILURE: the {}-th chunk of circuits, "
                                "can not get job id, Resubmit the qobj to get job id. "
                                "Unknown error: {} ".format(idx, e))
                    jobs[idx] = job
                    job_ids[idx] = job_id
    else:
        results = []
        for job in jobs:
            results.append(job.result(**qjob_config))

    result = _combine_result_objects(results) if len(results) != 0 else None

    return result
Exemplo n.º 4
0
def run_circuits(circuits,
                 backend,
                 execute_config,
                 qjob_config={},
                 max_circuits_per_job=sys.maxsize,
                 show_circuit_summary=False):
    """
    An execution wrapper with Qiskit-Terra, with job auto recover capability.

    The autorecovery feature is only applied for non-simulator backend.
    This wraper will try to get the result no matter how long it costs.

    Args:
        circuits (QuantumCircuit or list[QuantumCircuit]): circuits to execute
        backend (str): name of backend
        execute_config (dict): settings for qiskit execute (or compile)
        qjob_config (dict): settings for job object, like timeout and wait
        max_circuits_per_job (int): the maximum number of job, default is unlimited but 300
                is limited if you submit to a remote backend
        show_circuit_summary (bool): showing the summary of submitted circuits.

    Returns:
        Result: Result object

    Raises:
        AlgorithmError: Any error except for JobError raised by Qiskit Terra
    """

    if not isinstance(circuits, list):
        circuits = [circuits]

    my_backend = get_backend(backend)
    with_autorecover = False if my_backend.configuration(
    )['simulator'] else True

    qobjs = []
    jobs = []
    chunks = int(np.ceil(len(circuits) / max_circuits_per_job))

    for i in range(chunks):
        sub_circuits = circuits[i * max_circuits_per_job:(i + 1) *
                                max_circuits_per_job]
        qobj = q_compile(sub_circuits, my_backend, **execute_config)
        job = my_backend.run(qobj)
        jobs.append(job)
        qobjs.append(qobj)

    if logger.isEnabledFor(logging.DEBUG) and show_circuit_summary:
        logger.debug(summarize_circuits(circuits))

    results = []
    if with_autorecover:

        logger.info("There are {} circuits and they are chunked into "
                    "{} chunks, each with {} circutis.".format(
                        len(circuits), chunks, max_circuits_per_job))

        for idx in range(len(jobs)):
            job = jobs[idx]
            job_id = job.id()
            logger.info("Running {}-th chunk circuits, job id: {}".format(
                idx, job_id))
            while True:
                try:
                    result = job.result(**qjob_config)
                    if result.status == 'COMPLETED':
                        results.append(result)
                        logger.info(
                            "COMPLETED the {}-th chunk of circuits, job id: {}"
                            .format(idx, job_id))
                        break
                    else:
                        logger.warning(
                            "FAILURE: the {}-th chunk of circuits, job id: {}".
                            format(idx, job_id))
                except JobError as e:
                    # if terra raise any error, which means something wrong, re-run it
                    logger.warning(
                        "FAILURE: the {}-th chunk of circuits, job id: {}, "
                        "Terra job error: {} ".format(idx, job_id, e))
                except Exception as e:
                    raise AlgorithmError(
                        "FAILURE: the {}-th chunk of circuits, job id: {}, "
                        "Terra unknown error: {} ".format(idx, job_id,
                                                          e)) from e

                # keep querying the status until it is okay.
                while True:
                    try:
                        job_status = job.status()
                        break
                    except JobError as e:
                        logger.warning(
                            "FAILURE: job id: {}, "
                            "status: 'FAIL_TO_GET_STATUS' Terra job error: {}".
                            format(job_id, e))
                        time.sleep(5)
                    except Exception as e:
                        raise AlgorithmError(
                            "FAILURE: job id: {}, "
                            "status: 'FAIL_TO_GET_STATUS' ({})".format(
                                job_id, e)) from e

                logger.info("Job status: {}".format(job_status))
                # when reach here, it means the job fails. let's check what kinds of failure it is.
                if job_status == JobStatus.DONE:
                    logger.info(
                        "Job ({}) is completed anyway, retrieve result from backend."
                        .format(job_id))
                    job = my_backend.retrieve_job(job_id)
                elif job_status == JobStatus.RUNNING or job_status == JobStatus.QUEUED:
                    logger.info("Job ({}) is {}, but encounter an exception, "
                                "recover it from backend.".format(
                                    job_id, job_status))
                    job = my_backend.retrieve_job(job_id)
                else:
                    logger.info(
                        "Fail to run Job ({}), resubmit it.".format(job_id))
                    qobj = qobjs[idx]
                    job = my_backend.run(qobj)
    else:
        results = []
        for job in jobs:
            results.append(job.result(**qjob_config))

    if len(results) != 0:
        result = functools.reduce(lambda x, y: x + y, results)
    else:
        result = None
    return result