Skip to content

Commit

Permalink
Merge pull request qiskit-community/qiskit-aqua#693 from chunfuchen/p…
Browse files Browse the repository at this point in the history
…arameterized_circuits

Use parameterized circuits to speed up some algorithms instead of using CircuitCache
  • Loading branch information
woodsp-ibm authored Oct 1, 2019
2 parents 59fd21f + 0095e13 commit 45e5c8c
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 217 deletions.
95 changes: 60 additions & 35 deletions qiskit/aqua/quantum_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@
import logging
import time
import os
import warnings

from qiskit.assembler.run_config import RunConfig
from qiskit import compiler

from .aqua_error import AquaError
from .utils import CircuitCache
from .utils.backend_utils import (is_ibmq_provider,
is_aer_provider,
is_statevector_backend,
is_simulator_backend,
is_local_backend,
is_aer_qasm,
support_backend_options)
from .utils.circuit_utils import summarize_circuits

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -199,23 +202,25 @@ def __init__(self, backend,
"and re-build it after that.", self._cals_matrix_refresh_period)

# setup others
# TODO: allow an external way to overwrite the setting circuit cache temporally
# when either setup cache via environment variable or constructor,
# the optimization level will be change to 0 to assure cache works.
circuit_cache = None
if os.environ.get('QISKIT_AQUA_CIRCUIT_CACHE', False) or circuit_caching:
if optimization_level is None or optimization_level == 0:
self._compile_config['optimization_level'] = 0
skip_qobj_deepcopy = True if os.environ.get('QISKIT_AQUA_CIRCUIT_CACHE', False) \
else skip_qobj_deepcopy
circuit_cache = CircuitCache(skip_qobj_deepcopy=skip_qobj_deepcopy,
cache_file=cache_file)
else:
logger.warning('CircuitCache cannot be used with optimization_level %s. '
'Caching has been disabled. To re-enable, please set '
'optimization_level = 0 or None.', optimization_level)
warnings.warn("circuit_caching will be removed at Qiskit Aqua 0.7+, "
"this setting will be ignored. "
"On the other hand, Qiskit Aqua does support "
"parameterized circuits for adaptive algorithms (e.g. VQE and VQC) "
"to avoid for compiling the circuit with the same topology "
"multiple times",
UserWarning)
if skip_qobj_deepcopy:
warnings.warn("skip_qobj_deepcopy was used along with circuit_caching, and since "
"circuit_cache will be removed at Qiskit Aqua 0.7+, "
"this setting will be ignored, too.",
UserWarning)
if cache_file:
warnings.warn("cache_file was used along with circuit_caching, and since "
"circuit_cache will be removed at Qiskit Aqua 0.7+, "
"this setting will be ignored, too.",
UserWarning)

self._circuit_cache = circuit_cache
if is_ibmq_provider(self._backend):
if skip_qobj_validation:
logger.warning("The skip Qobj validation does not work "
Expand All @@ -242,28 +247,57 @@ def __str__(self):

return info

def execute(self, circuits, **kwargs):
def transpile(self, circuits):
"""
A wrapper to transpile circuits to allow algorithm access the transpiled circuits.
Args:
circuits (QuantumCircuit or list[QuantumCircuit]): circuits to transpile
Returns:
list[QuantumCircuit]: the transpiled circuits, it is always a list even though
the length is one.
"""
transpiled_circuits = compiler.transpile(circuits, self._backend, **self._backend_config,
**self._compile_config)
if not isinstance(transpiled_circuits, list):
transpiled_circuits = [transpiled_circuits]

if logger.isEnabledFor(logging.DEBUG) and self._circuit_summary:
logger.debug("==== Before transpiler ====")
logger.debug(summarize_circuits(circuits))
if transpiled_circuits is not None:
logger.debug("==== After transpiler ====")
logger.debug(summarize_circuits(transpiled_circuits))

return transpiled_circuits

def execute(self, circuits, had_transpiled=False, **kwargs):
"""
A wrapper to interface with quantum backend.
Args:
circuits (QuantumCircuit or list[QuantumCircuit]): circuits to execute
kwargs (list): additional parameters
had_transpiled (bool, optional): whether or not circuits had been transpiled
kwargs (dict, optional): additional parameters
Returns:
Result: Result object
TODO: Maybe we can combine the circuits for the main ones and calibration circuits before
assembling to the qobj.
"""
from .utils.run_circuits import (run_qobj,
compile_circuits)
maybe_add_aer_expectation_instruction)

from .utils.measurement_error_mitigation import (get_measured_qubits_from_qobj,
build_measurement_error_mitigation_qobj)
# maybe compile
if not had_transpiled:
circuits = self.transpile(circuits)

qobj = compile_circuits(circuits, self._backend, self._backend_config,
self._compile_config, self._run_config,
show_circuit_summary=self._circuit_summary,
circuit_cache=self._circuit_cache,
**kwargs)
# assemble
qobj = compiler.assemble(circuits, **self._run_config.to_dict())
if is_aer_provider(self._backend):
qobj = maybe_add_aer_expectation_instruction(qobj, kwargs)

if self._meas_error_mitigation_cls is not None:
qubit_index = get_measured_qubits_from_qobj(qobj)
Expand Down Expand Up @@ -319,6 +353,7 @@ def execute(self, circuits, **kwargs):
self._backend_options, self._noise_config,
self._skip_qobj_validation, self._job_callback)
else:
# insert the calibration circuit into main qobj if the shots are the same
qobj.experiments[0:0] = cals_qobj.experiments
result = run_qobj(qobj, self._backend, self._qjob_config,
self._backend_options, self._noise_config,
Expand Down Expand Up @@ -483,16 +518,6 @@ def is_local(self):
"""Return True if backend is a local backend."""
return is_local_backend(self._backend)

@property
def circuit_cache(self):
""" returns circuit cache """
return self._circuit_cache

@property
def has_circuit_caching(self):
""" checks if it has circuit cache """
return self._circuit_cache is not None

@property
def skip_qobj_validation(self):
""" checks if skip qobj validation """
Expand Down Expand Up @@ -524,7 +549,7 @@ def cals_matrix(self, qubit_index=None):
Get the stored calibration matrices and its timestamp.
Args:
qubit_index (int): the qubit index of corresponding calibration matrix.
qubit_index (list[int]): the qubit index of corresponding calibration matrix.
If None, return all stored calibration matrices.
Returns:
Expand Down
8 changes: 4 additions & 4 deletions qiskit/aqua/utils/measurement_error_mitigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@

import logging

from qiskit import compiler
from qiskit.ignis.mitigation.measurement import (complete_meas_cal,
CompleteMeasFitter, TensoredMeasFitter)

from .run_circuits import compile_circuits
from ..aqua_error import AquaError

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -121,7 +121,7 @@ def build_measurement_error_mitigation_qobj(qubit_list, fitter_cls, backend,
else:
raise AquaError("Unknown fitter {}".format(fitter_cls))

cals_qobj = compile_circuits(meas_calibs_circuits,
backend, backend_config, compile_config, run_config)

t_meas_calibs_circuits = compiler.transpile(meas_calibs_circuits, backend,
**backend_config, **compile_config)
cals_qobj = compiler.assemble(t_meas_calibs_circuits, backend, **run_config.to_dict())
return cals_qobj, state_labels, circlabel
Loading

0 comments on commit 45e5c8c

Please sign in to comment.