Skip to content

Commit

Permalink
Allow Optimizers as input to VQEProgram (#290) (#291)
Browse files Browse the repository at this point in the history
* allow Optimizers as optimizer inputs

* Update releasenotes/notes/vqeprogram-optimizers-cd23307c10fcd15b.yaml

Co-authored-by: Panagiotis Barkoutsos <[email protected]>
(cherry picked from commit e6a2dfd)

Co-authored-by: Julien Gacon <[email protected]>
  • Loading branch information
mergify[bot] and Cryoris authored Jul 29, 2021
1 parent 6b99674 commit 31e7359
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 19 deletions.
37 changes: 21 additions & 16 deletions qiskit_nature/runtime/vqe_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
"""The Qiskit Nature VQE Quantum Program."""


from typing import List, Callable, Optional, Any, Dict
from typing import List, Callable, Optional, Any, Dict, Union
import numpy as np

from qiskit import QuantumCircuit
from qiskit.exceptions import QiskitError
from qiskit.providers import Provider
from qiskit.providers.backend import Backend
from qiskit.algorithms import MinimumEigensolver, MinimumEigensolverResult, VQEResult
from qiskit.algorithms.optimizers import Optimizer, SPSA
from qiskit.opflow import OperatorBase, PauliSumOp
from qiskit.quantum_info import SparsePauliOp

Expand All @@ -31,7 +32,7 @@ class VQEProgram(MinimumEigensolver):
def __init__(
self,
ansatz: QuantumCircuit,
optimizer: Optional[Dict[str, Any]] = None,
optimizer: Optional[Union[Optimizer, Dict[str, Any]]] = None,
initial_point: Optional[np.ndarray] = None,
provider: Optional[Provider] = None,
backend: Optional[Backend] = None,
Expand All @@ -43,11 +44,11 @@ def __init__(
"""
Args:
ansatz: A parameterized circuit used as Ansatz for the wave function.
optimizer: A dictionary specifying a classical optimizer.
Currently only SPSA and QN-SPSA are supported. Per default, SPSA is used.
The dictionary must contain a key ``name`` for the name of the optimizer and may
contain additional keys for the settings.
E.g. ``{'name': 'SPSA', 'maxiter': 100}``.
optimizer: An optimizer or dictionary specifying a classical optimizer.
If a dictionary, only SPSA and QN-SPSA are supported. The dictionary must contain a
key ``name`` for the name of the optimizer and may contain additional keys for the
settings. E.g. ``{'name': 'SPSA', 'maxiter': 100}``.
Per default, SPSA is used.
backend: The backend to run the circuits on.
initial_point: An optional initial point (i.e. initial parameter values)
for the optimizer. If ``None`` a random vector is used.
Expand All @@ -62,7 +63,7 @@ def __init__(
steps. Per default False.
"""
if optimizer is None:
optimizer = {"name": "SPSA"}
optimizer = SPSA(maxiter=300)

# define program name
self._program_id = "vqe"
Expand Down Expand Up @@ -116,21 +117,25 @@ def ansatz(self, ansatz: QuantumCircuit) -> None:
self._ansatz = ansatz

@property
def optimizer(self) -> Dict[str, Any]:
def optimizer(self) -> Union[Optimizer, Dict[str, Any]]:
"""Return the dictionary describing the optimizer."""
return self._optimizer

@optimizer.setter
def optimizer(self, settings: Dict[str, Any]) -> None:
def optimizer(self, optimizer: Union[Optimizer, Dict[str, Any]]) -> None:
"""Set the optimizer."""
if "name" not in settings.keys():
raise ValueError(
"The settings must contain a ``name`` key specifying the type of " "the optimizer."
)
if isinstance(optimizer, Optimizer):
self._optimizer = optimizer
else:
if "name" not in optimizer.keys():
raise ValueError(
"The optimizer dictionary must contain a ``name`` key specifying the type "
"of the optimizer."
)

_validate_optimizer_settings(settings)
_validate_optimizer_settings(optimizer)

self._optimizer = settings
self._optimizer = optimizer

@property
def backend(self) -> Optional[Backend]:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
Allow Qiskit's :class:`~qiskit.algorithms.optimizers.Optimizer` classes as input for
the ``optimizer`` in the :class:`~qiskit_nature.runtime.VQEProgram` instead of only
dictionaries.
3 changes: 2 additions & 1 deletion test/runtime/fake_vqeruntime.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from typing import Dict, Any
import numpy as np
from qiskit.algorithms.optimizers import Optimizer
from qiskit.circuit import QuantumCircuit
from qiskit.opflow import PauliSumOp
from qiskit.providers import Provider
Expand Down Expand Up @@ -59,7 +60,7 @@ def run(self, program_id, inputs, options, callback=None):
"aux_operators": (list, type(None)),
"ansatz": QuantumCircuit,
"initial_point": (np.ndarray, str),
"optimizer": dict,
"optimizer": (Optimizer, dict),
"shots": int,
"measurement_error_mitigation": bool,
"store_intermediate": bool,
Expand Down
7 changes: 5 additions & 2 deletions test/runtime/test_vqeprogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
from test import QiskitNatureTestCase

import unittest
from ddt import ddt, data
import numpy as np
from qiskit.providers.basicaer import QasmSimulatorPy
from qiskit.algorithms import VQEResult
from qiskit.algorithms.optimizers import SPSA
from qiskit.circuit.library import RealAmplitudes
from qiskit.opflow import I, Z

Expand All @@ -26,19 +28,20 @@
from .fake_vqeruntime import FakeRuntimeProvider


@ddt
class TestVQEProgram(QiskitNatureTestCase):
"""Test the VQE program."""

def setUp(self):
super().setUp()
self.provider = FakeRuntimeProvider()

def test_standard_case(self):
@data({"name": "SPSA", "maxiter": 100}, SPSA(maxiter=100))
def test_standard_case(self, optimizer):
"""Test a standard use case."""
circuit = RealAmplitudes(3)
operator = Z ^ I ^ Z
initial_point = np.random.random(circuit.num_parameters)
optimizer = {"name": "SPSA", "maxiter": 100}
backend = QasmSimulatorPy()

vqe = VQEProgram(
Expand Down

0 comments on commit 31e7359

Please sign in to comment.