Skip to content

Commit 6fe8157

Browse files
ZoufalcCryorist-imamichiBryceFullermanoelmarques
authored
Gradients Framework (qiskit-community/qiskit-aqua#1293)
* clean PR with the current gradient state * Update derivatives_base.py * Update hessian.py * Update test_grad.py * add notebooks * Typing, Linting * Update gradient_framework.ipynb * typing qfi * enable gradients for VQAlgorithms * remove old files and notes * enfoce num chars <= 100 * fix an import * re-adjust import * fix other imports * additional base classes * test cases pass and the core logic all works. Doc strings could use another look. Same goes for some of the class method names inside of LinCombQFI and OverlapQFI * Update derivatives_base.py (qiskit-community/qiskit-aqua#75) * Update derivatives_base.py Added some doc-strings to several methods inside of derivatives_base.py. Also simplified the logic of `erase_operator_coeffs` by removing some leftover logic from previous implementations. * Update qiskit/aqua/operators/gradients/derivatives_base.py Co-authored-by: Julien Gacon <[email protected]> * update ordering/naming * reshuffle, rename * add VQE gradient unittest * add notebook B2Meeting This notebook will be removed after today - sorry but this is the best way to share this notebook with @bryce * Update gradient_framework_reduced.ipynb * removed a leftover notebook file * removed the notebooks (and am pushing them to a cleaned up QGradients repo) * Update gradient.py This small change prevents trivial/zero operators from appearing in SummedOps during product rule computations. * will be deleted need this to pull sry * fix qfi docstring * Add retworkx version check * delete notebooks, fixed seed fin_diff circSampler, fix kwargs import error * Delete test_natural_gradient.py * fix symbol map in parameter expression grad * typing * Update qfi.py * typing * Update test_grad.py * added a docstring to unroll_operator * Update hessian.py * Update gradient.py * Fix statevector check (not always a QuantumInstance) * Update hessian.py * fix lint of qiskit/aqua/operators/gradients/*.py * fix lint of qiskit/aqua/operators/gradients/circuit_gradients/*.py * fix lint of qiskit/aqua/operators/gradients/circuit_qfis/*.py * fix test_grad * Copy folder * remove unknown aqua changes * fix ListOp, VQAlgorithms for gradients * VQE Gradients import * update operators init * rm some changes not related to gradients * mypy fixes * skip jax test if not installed * try to fix cyclic import * fix lint in isinstance * uncomment vqe tests + consistent HAS_JAX * mypy fixes * ignore mypy warning from opbase.coeff * fix isinstance used w/ typehints * try fixing sphinx * ignore cases mypy doesn't understand correctly * fix unnecessary else after raise * Add jax to github actions * fix spell * add jax dependency to actions lint * fix spell * Reduce VQE Iterations in unittest * Use ImportError * fix lint * Add gradient framework release note * update gradient framework release note * fix reno formatting errors * Update to documentation * Fix doctring to avoid warnings * update gradient init * update qaoa docstring * remover retworkx check * update docstrings * lint fixes * update docstrings to hint max_evals_grouped deprecation if gradient is given * Update test_grad.py Several high-level function calls still used a `method=...` argument in the initialization; however, we changed this to `grad_method`, `hess_method`, `qfi_method`. So I updated these arguments. This was causing some tests to not be carried out as the default argument was inferred when the correct argument name was not assigned a method type. * Update test_grad.py Added a test case for Hessian.py that forces it to differentiate an operator with a custom combo_fn * Update lin_comb circuit gradients to fix hessian evaluation * Move renamed gradient test into operator file * update lin_comb * update lin_comb gradients * fix lint * fix lin_comb * fixed the bugs that were causing Hessian logic to fail with custom combo_fns * increase coverage of natural gradient * merge zoufalc gradients * try all combinations of grad_method and qfi_method * style fix * updates for hessians * remove redundant line * make fixes * remove hessian from grad * relax VQE test * remove redundant lambda * fix identation * fix spelling * fix whitespace * revert qfi_method in test_natural_gradient * revert param name * fix lint * remove redundant comment * update identation * fix np.random.seed * increase coverage for lin_comb * fix lint * lint * whitespace fix * docstring * lint * disable misspelling * add yy, zz to pylintdict * Update __init__.py updated the gradients __init__ file with some of the content from the release note * fixed linting * update init file * fix spell * fix spelling * remove redundant import * attempt to fix sphinx qiskit-community/qiskit-aqua#1 * Update qiskit/aqua/operators/gradients/qfi.py Co-authored-by: Julien Gacon <[email protected]> * try to fix sphinx no.2 * add words to pylintdict * fix cryoris comments * Update qiskit/aqua/operators/gradients/circuit_qfis/lin_comb_full.py Co-authored-by: Julien Gacon <[email protected]> * Update qiskit/aqua/operators/gradients/circuit_qfis/lin_comb_full.py Co-authored-by: Julien Gacon <[email protected]> * Update qiskit/aqua/operators/gradients/circuit_qfis/lin_comb_full.py Co-authored-by: Julien Gacon <[email protected]> * cryoris comments * delete unneccessary * Update qiskit/aqua/operators/gradients/hessian.py Co-authored-by: Julien Gacon <[email protected]> * raise warning hessians * include docstring TypeError * Update qiskit/aqua/operators/gradients/circuit_qfis/overlap_diag.py Co-authored-by: Julien Gacon <[email protected]> * Update qiskit/aqua/operators/gradients/gradient.py Co-authored-by: Julien Gacon <[email protected]> * remove unnecessary os comment * Update qiskit/aqua/operators/gradients/circuit_gradients/lin_comb.py Co-authored-by: Julien Gacon <[email protected]> * Insert proper Error * apply changes from code review Co-authored-by: Cryoris <[email protected]> Co-authored-by: Takashi Imamichi <[email protected]> Co-authored-by: Bryce-Fuller <[email protected]> Co-authored-by: Julien Gacon <[email protected]> Co-authored-by: Manoel Marques <[email protected]> Co-authored-by: Manoel Marques <[email protected]> Co-authored-by: woodsp <[email protected]> Co-authored-by: Steve Wood <[email protected]> Co-authored-by: Julien Gacon <[email protected]>
1 parent fddb7e0 commit 6fe8157

File tree

4 files changed

+938
-2
lines changed

4 files changed

+938
-2
lines changed

qiskit/aqua/algorithms/minimum_eigen_solvers/qaoa/qaoa.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from qiskit.providers import Backend
2121
from qiskit.aqua import QuantumInstance
2222
from qiskit.aqua.operators import OperatorBase, ExpectationBase, LegacyBaseOperator
23+
from qiskit.aqua.operators.gradients import GradientBase
2324
from qiskit.aqua.components.initial_states import InitialState
2425
from qiskit.aqua.components.optimizers import Optimizer
2526
from qiskit.aqua.utils.validation import validate_min
@@ -69,6 +70,8 @@ def __init__(self,
6970
initial_state: Optional[InitialState] = None,
7071
mixer: Union[OperatorBase, LegacyBaseOperator] = None,
7172
initial_point: Optional[np.ndarray] = None,
73+
gradient: Optional[Union[GradientBase, Callable[[Union[np.ndarray, List]],
74+
List]]] = None,
7275
expectation: Optional[ExpectationBase] = None,
7376
include_custom: bool = False,
7477
max_evals_grouped: int = 1,
@@ -88,6 +91,8 @@ def __init__(self,
8891
constrained subspaces as per https://arxiv.org/abs/1709.03489
8992
initial_point: An optional initial point (i.e. initial parameter values)
9093
for the optimizer. If ``None`` then it will simply compute a random one.
94+
gradient: An optional gradient operator respectively a gradient function used for
95+
optimization.
9196
expectation: The Expectation converter for taking the average value of the
9297
Observable over the var_form state function. When None (the default) an
9398
:class:`~qiskit.aqua.operators.expectations.ExpectationFactory` is used to select
@@ -105,7 +110,8 @@ def __init__(self,
105110
potentially the expectation values can be computed in parallel. Typically this is
106111
possible when a finite difference gradient is used by the optimizer such that
107112
multiple points to compute the gradient can be passed and if computed in parallel
108-
improve overall execution time.
113+
improve overall execution time. Ignored if a gradient operator or function is
114+
given.
109115
aux_operators: Optional list of auxiliary operators to be evaluated with the eigenstate
110116
of the minimum eigenvalue main result and their expectation values returned.
111117
For instance in chemistry these can be dipole operators, total particle count
@@ -129,6 +135,7 @@ def __init__(self,
129135
None,
130136
optimizer,
131137
initial_point=initial_point,
138+
gradient=gradient,
132139
expectation=expectation,
133140
include_custom=include_custom,
134141
max_evals_grouped=max_evals_grouped,

qiskit/aqua/algorithms/minimum_eigen_solvers/vqe.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from qiskit.aqua.algorithms import QuantumAlgorithm
3131
from qiskit.aqua.operators import (OperatorBase, ExpectationBase, ExpectationFactory, StateFn,
3232
CircuitStateFn, LegacyBaseOperator, ListOp, I, CircuitSampler)
33+
from qiskit.aqua.operators.gradients import GradientBase
3334
from qiskit.aqua.components.optimizers import Optimizer, SLSQP
3435
from qiskit.aqua.components.variational_forms import VariationalForm
3536
from qiskit.aqua.utils.validation import validate_min
@@ -91,6 +92,7 @@ def __init__(self,
9192
var_form: Optional[Union[QuantumCircuit, VariationalForm]] = None,
9293
optimizer: Optional[Optimizer] = None,
9394
initial_point: Optional[np.ndarray] = None,
95+
gradient: Optional[Union[GradientBase, Callable]] = None,
9496
expectation: Optional[ExpectationBase] = None,
9597
include_custom: bool = False,
9698
max_evals_grouped: int = 1,
@@ -108,6 +110,7 @@ def __init__(self,
108110
initial_point: An optional initial point (i.e. initial parameter values)
109111
for the optimizer. If ``None`` then VQE will look to the variational form for a
110112
preferred point and if not will simply compute a random one.
113+
gradient: An optional gradient function or operator for optimizer.
111114
expectation: The Expectation converter for taking the average value of the
112115
Observable over the var_form state function. When ``None`` (the default) an
113116
:class:`~qiskit.aqua.operators.expectations.ExpectationFactory` is used to select
@@ -125,7 +128,8 @@ def __init__(self,
125128
potentially the expectation values can be computed in parallel. Typically this is
126129
possible when a finite difference gradient is used by the optimizer such that
127130
multiple points to compute the gradient can be passed and if computed in parallel
128-
improve overall execution time.
131+
improve overall execution time. Deprecated if a gradient operator or function is
132+
given.
129133
aux_operators: Optional list of auxiliary operators to be evaluated with the
130134
eigenstate of the minimum eigenvalue main result and their expectation values
131135
returned. For instance in chemistry these can be dipole operators, total particle
@@ -159,6 +163,7 @@ def __init__(self,
159163
super().__init__(var_form=var_form,
160164
optimizer=optimizer,
161165
cost_fn=self._energy_evaluation,
166+
gradient=gradient,
162167
initial_point=initial_point,
163168
quantum_instance=quantum_instance)
164169
self._ret = None # type: Dict[str, Any]
@@ -412,9 +417,19 @@ def _run(self) -> 'VQEResult':
412417
self._quantum_instance.circuit_summary = True
413418

414419
self._eval_count = 0
420+
421+
# Convert the gradient operator into a callable function that is compatible with the
422+
# optimization routine.
423+
if self._gradient:
424+
if isinstance(self._gradient, GradientBase):
425+
self._gradient = self._gradient.gradient_wrapper(
426+
~StateFn(self._operator) @ StateFn(self._var_form),
427+
bind_params=self._var_form_params,
428+
backend=self._quantum_instance)
415429
vqresult = self.find_minimum(initial_point=self.initial_point,
416430
var_form=self.var_form,
417431
cost_fn=self._energy_evaluation,
432+
gradient_fn=self._gradient,
418433
optimizer=self.optimizer)
419434

420435
# TODO remove all former dictionary logic

qiskit/aqua/algorithms/vq_algorithm.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from qiskit.aqua.algorithms import AlgorithmResult, QuantumAlgorithm
3535
from qiskit.aqua.components.optimizers import Optimizer, SLSQP
3636
from qiskit.aqua.components.variational_forms import VariationalForm
37+
from qiskit.aqua.operators.gradients import GradientBase
3738

3839
logger = logging.getLogger(__name__)
3940

@@ -47,6 +48,7 @@ def __init__(self,
4748
var_form: Union[QuantumCircuit, VariationalForm],
4849
optimizer: Optimizer,
4950
cost_fn: Optional[Callable] = None,
51+
gradient: Optional[Union[GradientBase, Callable]] = None,
5052
initial_point: Optional[np.ndarray] = None,
5153
quantum_instance: Optional[
5254
Union[QuantumInstance, BaseBackend, Backend]] = None) -> None:
@@ -56,6 +58,7 @@ def __init__(self,
5658
optimizer: A classical optimizer.
5759
cost_fn: An optional cost function for optimizer. If not supplied here must be
5860
supplied on :meth:`find_minimum`.
61+
gradient: An optional gradient operator or function for optimizer.
5962
initial_point: An optional initial point (i.e. initial parameter values)
6063
for the optimizer.
6164
quantum_instance: Quantum Instance or Backend
@@ -70,6 +73,7 @@ def __init__(self,
7073
optimizer = SLSQP()
7174

7275
self._optimizer = optimizer
76+
self._gradient = gradient
7377
self._cost_fn = cost_fn
7478
self._initial_point = initial_point
7579
self._var_form = var_form
@@ -197,6 +201,9 @@ def find_minimum(self,
197201
start = time.time()
198202
if not optimizer.is_gradient_supported: # ignore the passed gradient function
199203
gradient_fn = None
204+
else:
205+
if not gradient_fn:
206+
gradient_fn = self._gradient
200207

201208
logger.info('Starting optimizer.\nbounds=%s\ninitial point=%s', bounds, initial_point)
202209
opt_params, opt_val, num_optimizer_evals = optimizer.optimize(nparms,

0 commit comments

Comments
 (0)