Skip to content

Commit

Permalink
A new algorithm_globals to replace use of qiskit.utils instance (#33)
Browse files Browse the repository at this point in the history
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
  • Loading branch information
woodsp-ibm and ElePT authored Aug 15, 2023
1 parent 6738c6d commit 9fe18e6
Show file tree
Hide file tree
Showing 35 changed files with 237 additions and 46 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ jobs:
run: |
sudo apt-get -y install pandoc graphviz python3-enchant hunspell-en-us
pip install pyenchant
# append to reno config
echo "earliest_version: 0.1.0" >> releasenotes/config.yaml
shell: bash
- run: pip check
if: ${{ !cancelled() }}
Expand Down Expand Up @@ -182,13 +184,13 @@ jobs:
run: |
pip install jupyter qiskit-terra[visualization]
sudo apt-get install -y pandoc graphviz
echo "earliest_version: 0.1.0" >> releasenotes/config.yaml
shell: bash
- name: Run Qiskit Algorithms Tutorials
env:
QISKIT_PARALLEL: False
QISKIT_DOCS_BUILD_TUTORIALS: 'always'
run: |
tools/ignore_untagged_notes.sh
make html
cd docs/_build/html
mkdir artifacts
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ coverage:
coverage_erase:
coverage erase

clean: coverage_erase;
clean: clean_sphinx coverage_erase;
12 changes: 10 additions & 2 deletions docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,22 @@ SPHINXOPTS =
SPHINXBUILD = sphinx-build
SOURCEDIR = .
BUILDDIR = _build
STUBSDIR = stubs

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile
spell:
@$(SPHINXBUILD) -M spelling "$(SOURCEDIR)" "$(BUILDDIR)" -W -T --keep-going $(SPHINXOPTS) $(O)

clean:
rm -rf $(BUILDDIR)
rm -rf $(STUBSDIR)

.PHONY: help spell clean Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" -W -T --keep-going $(SPHINXOPTS) $(O)
6 changes: 6 additions & 0 deletions docs/apidocs/qiskit_algorithms.utils.algorithm_globals.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _qiskit_algorithms.utils.algorithm_globals:

.. automodule:: qiskit_algorithms.utils.algorithm_globals
:no-members:
:no-inherited-members:
:no-special-members:
7 changes: 6 additions & 1 deletion qiskit_algorithms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,18 @@
Utility classes
---------------
Utility classes used by algorithms (mainly for type-hinting purposes).
Utility classes and function used by algorithms.
.. autosummary::
:toctree: ../stubs/
AlgorithmJob
.. autosummary::
:toctree:
utils.algorithm_globals
"""
from .algorithm_job import AlgorithmJob
from .algorithm_result import AlgorithmResult
Expand Down
2 changes: 1 addition & 1 deletion qiskit_algorithms/amplitude_amplifiers/grover.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
from qiskit import ClassicalRegister, QuantumCircuit
from qiskit.primitives import BaseSampler
from qiskit.quantum_info import Statevector
from qiskit.utils import algorithm_globals

from qiskit_algorithms.exceptions import AlgorithmError
from qiskit_algorithms.utils import algorithm_globals

from .amplification_problem import AmplificationProblem
from .amplitude_amplifier import AmplitudeAmplifier, AmplitudeAmplifierResult
Expand Down
7 changes: 0 additions & 7 deletions qiskit_algorithms/optimizers/adam_amsgrad.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,6 @@ class ADAM(Optimizer):
[2]: Sashank J. Reddi and Satyen Kale and Sanjiv Kumar (2018),
On the Convergence of Adam and Beyond.
`arXiv:1904.09237 <https://arxiv.org/abs/1904.09237>`_
.. note::
This component has some function that is normally random. If you want to reproduce behavior
then you should set the random number generator seed in the algorithm_globals
(``qiskit.utils.algorithm_globals.random_seed = seed``).
"""

_OPTIONS = [
Expand Down
5 changes: 3 additions & 2 deletions qiskit_algorithms/optimizers/gsls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

from collections.abc import Callable
from typing import Any, SupportsFloat

import numpy as np

from qiskit.utils import algorithm_globals
from qiskit_algorithms.utils import algorithm_globals
from .optimizer import Optimizer, OptimizerSupportLevel, OptimizerResult, POINT


Expand All @@ -33,7 +34,7 @@ class GSLS(Optimizer):
This component has some function that is normally random. If you want to reproduce behavior
then you should set the random number generator seed in the algorithm_globals
(``qiskit.utils.algorithm_globals.random_seed = seed``).
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
"""

_OPTIONS = [
Expand Down
10 changes: 8 additions & 2 deletions qiskit_algorithms/optimizers/p_bfgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@

import numpy as np

from qiskit.utils import algorithm_globals

from qiskit_algorithms.utils import algorithm_globals
from qiskit_algorithms.utils.validation import validate_min

from .optimizer import OptimizerResult, POINT
from .scipy_optimizer import SciPyOptimizer

Expand All @@ -42,6 +42,12 @@ class P_BFGS(SciPyOptimizer): # pylint: disable=invalid-name
Uses scipy.optimize.fmin_l_bfgs_b.
For further detail, please refer to
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_l_bfgs_b.html
.. note::
This component has some function that is normally random. If you want to reproduce behavior
then you should set the random number generator seed in the algorithm_globals
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
"""

_OPTIONS = ["maxfun", "ftol", "iprint"]
Expand Down
2 changes: 1 addition & 1 deletion qiskit_algorithms/optimizers/qnspsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class QNSPSA(SPSA):
This component has some function that is normally random. If you want to reproduce behavior
then you should set the random number generator seed in the algorithm_globals
(``qiskit.utils.algorithm_globals.random_seed = seed``).
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
Examples:
Expand Down
4 changes: 2 additions & 2 deletions qiskit_algorithms/optimizers/spsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import scipy
import numpy as np

from qiskit.utils import algorithm_globals
from qiskit_algorithms.utils import algorithm_globals

from .optimizer import Optimizer, OptimizerSupportLevel, OptimizerResult, POINT

Expand Down Expand Up @@ -77,7 +77,7 @@ class SPSA(Optimizer):
This component has some function that is normally random. If you want to reproduce behavior
then you should set the random number generator seed in the algorithm_globals
(``qiskit.utils.algorithm_globals.random_seed = seed``).
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
Examples:
Expand Down
9 changes: 7 additions & 2 deletions qiskit_algorithms/optimizers/umda.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@

from collections.abc import Callable
from typing import Any

import numpy as np
from scipy.stats import norm
from qiskit.utils import algorithm_globals

from qiskit_algorithms.utils import algorithm_globals
from .optimizer import OptimizerResult, POINT
from .scipy_optimizer import Optimizer, OptimizerSupportLevel

Expand Down Expand Up @@ -72,7 +73,6 @@ class UMDA(Optimizer):
from qiskit_algorithms.optimizers import UMDA
from qiskit_algorithms import QAOA
from qiskit.utils import QuantumInstance
from qiskit.quantum_info import Pauli
from qiskit.primitives import Sampler
Expand Down Expand Up @@ -102,6 +102,11 @@ class UMDA(Optimizer):
qaoa = QAOA(Sampler(), opt,reps=p)
result = qaoa.compute_minimum_eigenvalue(operator=H2_op)
.. note::
This component has some function that is normally random. If you want to reproduce behavior
then you should set the random number generator seed in the algorithm_globals
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
References:
Expand Down
2 changes: 1 addition & 1 deletion qiskit_algorithms/time_evolvers/pvqd/pvqd.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from qiskit.primitives import BaseEstimator
from qiskit.quantum_info.operators.base_operator import BaseOperator
from qiskit.synthesis import EvolutionSynthesis, LieTrotter
from qiskit.utils import algorithm_globals
from qiskit_algorithms.utils import algorithm_globals

from ...exceptions import AlgorithmError
from ...optimizers import Minimizer, Optimizer
Expand Down
2 changes: 2 additions & 0 deletions qiskit_algorithms/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@

"""Common qiskit_algorithms utility functions."""

from .algorithm_globals import algorithm_globals
from .validate_initial_point import validate_initial_point
from .validate_bounds import validate_bounds

__all__ = [
"algorithm_globals",
"validate_initial_point",
"validate_bounds",
]
122 changes: 122 additions & 0 deletions qiskit_algorithms/utils/algorithm_globals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# This code is part of a Qiskit project.
#
# (C) Copyright IBM 2019, 2023.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
utils.algorithm_globals
=======================
Common (global) properties used across qiskit_algorithms.
.. currentmodule:: qiskit_algorithms.utils.algorithm_globals
Includes:
* Random number generator and random seed.
Algorithms can use the generator for random values, as needed, and it
can be seeded here for reproducible results when using such an algorithm.
This is often important, for example in unit tests, where the same
outcome is desired each time (reproducible) and not have it be variable
due to randomness.
Attributes:
random_seed (int | None): Random generator seed (read/write).
random (np.random.Generator): Random generator (read-only)
"""

from __future__ import annotations

import warnings

import numpy as np


class QiskitAlgorithmGlobals:
"""Global properties for algorithms."""

# The code is done to work even after some future removal of algorithm_globals
# from Qiskit (qiskit.utils). All that is needed in the future, after that, if
# this is updated, is just the logic in the except blocks.
#
# If the Qiskit version exists this acts a redirect to that (it delegates the
# calls off to it). In the future when that does not exist this has similar code
# in the except blocks here, as noted above, that will take over. By delegating
# to the Qiskit instance it means that any existing code that uses that continues
# to work. Logic here in qiskit_algorithms though uses this instance and the
# random check here has logic to warn if the seed here is not the same as the Qiskit
# version so we can detect direct usage of the Qiskit version and alert the user to
# change their code to use this. So simply changing from:
# from qiskit.utils import algorithm_globals
# to
# from qiskit_algorithm.utils import algorithm_globals

def __init__(self) -> None:
self._random_seed: int | None = None
self._random = None

@property
def random_seed(self) -> int | None:
"""Random seed property (getter/setter)."""
try:
from qiskit.utils import algorithm_globals as qiskit_globals

return qiskit_globals.random_seed

except ImportError:
return self._random_seed

@random_seed.setter
def random_seed(self, seed: int | None) -> None:
"""Set the random generator seed.
Args:
seed: If ``None`` then internally a random value is used as a seed
"""
try:
from qiskit.utils import algorithm_globals as qiskit_globals

qiskit_globals.random_seed = seed
# Mirror the seed here when set via this random_seed. If the seed is
# set on the qiskit.utils instance then we can detect it's different
self._random_seed = seed

except ImportError:
self._random_seed = seed
self._random = None

@property
def random(self) -> np.random.Generator:
"""Return a numpy np.random.Generator (default_rng) using random_seed."""
try:
from qiskit.utils import algorithm_globals as qiskit_globals

if self._random_seed != qiskit_globals.random_seed:
# If the seeds are different - likely this local is None and the qiskit.utils
# algorithms global was seeded directly then we will warn to use this here as
# the Qiskit version is planned to be removed in a future version of Qiskit.
warnings.warn(
"Using random that is seeded via qiskit.utils algorithm_globals is deprecated "
"since version 0.2.0. Instead set random_seed directly to "
"qiskit_algorithms.utils algorithm_globals.",
category=DeprecationWarning,
stacklevel=2,
)

return qiskit_globals.random

except ImportError:
if self._random is None:
self._random = np.random.default_rng(self._random_seed)
return self._random


# Global instance to be used as the entry point for globals.
algorithm_globals = QiskitAlgorithmGlobals()
2 changes: 1 addition & 1 deletion qiskit_algorithms/utils/validate_initial_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import numpy as np

from qiskit.circuit import QuantumCircuit
from qiskit.utils import algorithm_globals
from qiskit_algorithms.utils import algorithm_globals


def validate_initial_point(
Expand Down
2 changes: 1 addition & 1 deletion qiskit_algorithms/variational_algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
This component has some function that is normally random. If you want to reproduce behavior
then you should set the random number generator seed in the algorithm_globals
(``qiskit.utils.algorithm_globals.random_seed = seed``).
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
"""

from __future__ import annotations
Expand Down
Loading

0 comments on commit 9fe18e6

Please sign in to comment.