Skip to content

Commit 9fe18e6

Browse files
woodsp-ibmElePT
andauthored
A new algorithm_globals to replace use of qiskit.utils instance (#33)
Co-authored-by: Elena Peña Tapia <[email protected]>
1 parent 6738c6d commit 9fe18e6

35 files changed

+237
-46
lines changed

.github/workflows/main.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ jobs:
6666
run: |
6767
sudo apt-get -y install pandoc graphviz python3-enchant hunspell-en-us
6868
pip install pyenchant
69+
# append to reno config
70+
echo "earliest_version: 0.1.0" >> releasenotes/config.yaml
6971
shell: bash
7072
- run: pip check
7173
if: ${{ !cancelled() }}
@@ -182,13 +184,13 @@ jobs:
182184
run: |
183185
pip install jupyter qiskit-terra[visualization]
184186
sudo apt-get install -y pandoc graphviz
187+
echo "earliest_version: 0.1.0" >> releasenotes/config.yaml
185188
shell: bash
186189
- name: Run Qiskit Algorithms Tutorials
187190
env:
188191
QISKIT_PARALLEL: False
189192
QISKIT_DOCS_BUILD_TUTORIALS: 'always'
190193
run: |
191-
tools/ignore_untagged_notes.sh
192194
make html
193195
cd docs/_build/html
194196
mkdir artifacts

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,4 @@ coverage:
7979
coverage_erase:
8080
coverage erase
8181

82-
clean: coverage_erase;
82+
clean: clean_sphinx coverage_erase;

docs/Makefile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,22 @@ SPHINXOPTS =
1515
SPHINXBUILD = sphinx-build
1616
SOURCEDIR = .
1717
BUILDDIR = _build
18+
STUBSDIR = stubs
1819

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

23-
.PHONY: help Makefile
24+
spell:
25+
@$(SPHINXBUILD) -M spelling "$(SOURCEDIR)" "$(BUILDDIR)" -W -T --keep-going $(SPHINXOPTS) $(O)
26+
27+
clean:
28+
rm -rf $(BUILDDIR)
29+
rm -rf $(STUBSDIR)
30+
31+
.PHONY: help spell clean Makefile
2432

2533
# Catch-all target: route all unknown targets to Sphinx using the new
2634
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
2735
%: Makefile
28-
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
36+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" -W -T --keep-going $(SPHINXOPTS) $(O)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.. _qiskit_algorithms.utils.algorithm_globals:
2+
3+
.. automodule:: qiskit_algorithms.utils.algorithm_globals
4+
:no-members:
5+
:no-inherited-members:
6+
:no-special-members:

qiskit_algorithms/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,18 @@
203203
Utility classes
204204
---------------
205205
206-
Utility classes used by algorithms (mainly for type-hinting purposes).
206+
Utility classes and function used by algorithms.
207207
208208
.. autosummary::
209209
:toctree: ../stubs/
210210
211211
AlgorithmJob
212212
213+
.. autosummary::
214+
:toctree:
215+
216+
utils.algorithm_globals
217+
213218
"""
214219
from .algorithm_job import AlgorithmJob
215220
from .algorithm_result import AlgorithmResult

qiskit_algorithms/amplitude_amplifiers/grover.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
from qiskit import ClassicalRegister, QuantumCircuit
2323
from qiskit.primitives import BaseSampler
2424
from qiskit.quantum_info import Statevector
25-
from qiskit.utils import algorithm_globals
2625

2726
from qiskit_algorithms.exceptions import AlgorithmError
27+
from qiskit_algorithms.utils import algorithm_globals
2828

2929
from .amplification_problem import AmplificationProblem
3030
from .amplitude_amplifier import AmplitudeAmplifier, AmplitudeAmplifierResult

qiskit_algorithms/optimizers/adam_amsgrad.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@ class ADAM(Optimizer):
4343
[2]: Sashank J. Reddi and Satyen Kale and Sanjiv Kumar (2018),
4444
On the Convergence of Adam and Beyond.
4545
`arXiv:1904.09237 <https://arxiv.org/abs/1904.09237>`_
46-
47-
.. note::
48-
49-
This component has some function that is normally random. If you want to reproduce behavior
50-
then you should set the random number generator seed in the algorithm_globals
51-
(``qiskit.utils.algorithm_globals.random_seed = seed``).
52-
5346
"""
5447

5548
_OPTIONS = [

qiskit_algorithms/optimizers/gsls.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616

1717
from collections.abc import Callable
1818
from typing import Any, SupportsFloat
19+
1920
import numpy as np
2021

21-
from qiskit.utils import algorithm_globals
22+
from qiskit_algorithms.utils import algorithm_globals
2223
from .optimizer import Optimizer, OptimizerSupportLevel, OptimizerResult, POINT
2324

2425

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

3940
_OPTIONS = [

qiskit_algorithms/optimizers/p_bfgs.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121

2222
import numpy as np
2323

24-
from qiskit.utils import algorithm_globals
25-
24+
from qiskit_algorithms.utils import algorithm_globals
2625
from qiskit_algorithms.utils.validation import validate_min
26+
2727
from .optimizer import OptimizerResult, POINT
2828
from .scipy_optimizer import SciPyOptimizer
2929

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

4753
_OPTIONS = ["maxfun", "ftol", "iprint"]

qiskit_algorithms/optimizers/qnspsa.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class QNSPSA(SPSA):
5151
5252
This component has some function that is normally random. If you want to reproduce behavior
5353
then you should set the random number generator seed in the algorithm_globals
54-
(``qiskit.utils.algorithm_globals.random_seed = seed``).
54+
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
5555
5656
Examples:
5757

qiskit_algorithms/optimizers/spsa.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import scipy
2727
import numpy as np
2828

29-
from qiskit.utils import algorithm_globals
29+
from qiskit_algorithms.utils import algorithm_globals
3030

3131
from .optimizer import Optimizer, OptimizerSupportLevel, OptimizerResult, POINT
3232

@@ -77,7 +77,7 @@ class SPSA(Optimizer):
7777
7878
This component has some function that is normally random. If you want to reproduce behavior
7979
then you should set the random number generator seed in the algorithm_globals
80-
(``qiskit.utils.algorithm_globals.random_seed = seed``).
80+
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
8181
8282
8383
Examples:

qiskit_algorithms/optimizers/umda.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616

1717
from collections.abc import Callable
1818
from typing import Any
19+
1920
import numpy as np
2021
from scipy.stats import norm
21-
from qiskit.utils import algorithm_globals
2222

23+
from qiskit_algorithms.utils import algorithm_globals
2324
from .optimizer import OptimizerResult, POINT
2425
from .scipy_optimizer import Optimizer, OptimizerSupportLevel
2526

@@ -72,7 +73,6 @@ class UMDA(Optimizer):
7273
7374
from qiskit_algorithms.optimizers import UMDA
7475
from qiskit_algorithms import QAOA
75-
from qiskit.utils import QuantumInstance
7676
from qiskit.quantum_info import Pauli
7777
from qiskit.primitives import Sampler
7878
@@ -102,6 +102,11 @@ class UMDA(Optimizer):
102102
qaoa = QAOA(Sampler(), opt,reps=p)
103103
result = qaoa.compute_minimum_eigenvalue(operator=H2_op)
104104
105+
.. note::
106+
107+
This component has some function that is normally random. If you want to reproduce behavior
108+
then you should set the random number generator seed in the algorithm_globals
109+
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
105110
106111
References:
107112

qiskit_algorithms/time_evolvers/pvqd/pvqd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from qiskit.primitives import BaseEstimator
2424
from qiskit.quantum_info.operators.base_operator import BaseOperator
2525
from qiskit.synthesis import EvolutionSynthesis, LieTrotter
26-
from qiskit.utils import algorithm_globals
26+
from qiskit_algorithms.utils import algorithm_globals
2727

2828
from ...exceptions import AlgorithmError
2929
from ...optimizers import Minimizer, Optimizer

qiskit_algorithms/utils/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212

1313
"""Common qiskit_algorithms utility functions."""
1414

15+
from .algorithm_globals import algorithm_globals
1516
from .validate_initial_point import validate_initial_point
1617
from .validate_bounds import validate_bounds
1718

1819
__all__ = [
20+
"algorithm_globals",
1921
"validate_initial_point",
2022
"validate_bounds",
2123
]
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# This code is part of a Qiskit project.
2+
#
3+
# (C) Copyright IBM 2019, 2023.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
"""
14+
utils.algorithm_globals
15+
=======================
16+
Common (global) properties used across qiskit_algorithms.
17+
18+
.. currentmodule:: qiskit_algorithms.utils.algorithm_globals
19+
20+
Includes:
21+
22+
* Random number generator and random seed.
23+
24+
Algorithms can use the generator for random values, as needed, and it
25+
can be seeded here for reproducible results when using such an algorithm.
26+
This is often important, for example in unit tests, where the same
27+
outcome is desired each time (reproducible) and not have it be variable
28+
due to randomness.
29+
30+
Attributes:
31+
random_seed (int | None): Random generator seed (read/write).
32+
random (np.random.Generator): Random generator (read-only)
33+
"""
34+
35+
from __future__ import annotations
36+
37+
import warnings
38+
39+
import numpy as np
40+
41+
42+
class QiskitAlgorithmGlobals:
43+
"""Global properties for algorithms."""
44+
45+
# The code is done to work even after some future removal of algorithm_globals
46+
# from Qiskit (qiskit.utils). All that is needed in the future, after that, if
47+
# this is updated, is just the logic in the except blocks.
48+
#
49+
# If the Qiskit version exists this acts a redirect to that (it delegates the
50+
# calls off to it). In the future when that does not exist this has similar code
51+
# in the except blocks here, as noted above, that will take over. By delegating
52+
# to the Qiskit instance it means that any existing code that uses that continues
53+
# to work. Logic here in qiskit_algorithms though uses this instance and the
54+
# random check here has logic to warn if the seed here is not the same as the Qiskit
55+
# version so we can detect direct usage of the Qiskit version and alert the user to
56+
# change their code to use this. So simply changing from:
57+
# from qiskit.utils import algorithm_globals
58+
# to
59+
# from qiskit_algorithm.utils import algorithm_globals
60+
61+
def __init__(self) -> None:
62+
self._random_seed: int | None = None
63+
self._random = None
64+
65+
@property
66+
def random_seed(self) -> int | None:
67+
"""Random seed property (getter/setter)."""
68+
try:
69+
from qiskit.utils import algorithm_globals as qiskit_globals
70+
71+
return qiskit_globals.random_seed
72+
73+
except ImportError:
74+
return self._random_seed
75+
76+
@random_seed.setter
77+
def random_seed(self, seed: int | None) -> None:
78+
"""Set the random generator seed.
79+
80+
Args:
81+
seed: If ``None`` then internally a random value is used as a seed
82+
"""
83+
try:
84+
from qiskit.utils import algorithm_globals as qiskit_globals
85+
86+
qiskit_globals.random_seed = seed
87+
# Mirror the seed here when set via this random_seed. If the seed is
88+
# set on the qiskit.utils instance then we can detect it's different
89+
self._random_seed = seed
90+
91+
except ImportError:
92+
self._random_seed = seed
93+
self._random = None
94+
95+
@property
96+
def random(self) -> np.random.Generator:
97+
"""Return a numpy np.random.Generator (default_rng) using random_seed."""
98+
try:
99+
from qiskit.utils import algorithm_globals as qiskit_globals
100+
101+
if self._random_seed != qiskit_globals.random_seed:
102+
# If the seeds are different - likely this local is None and the qiskit.utils
103+
# algorithms global was seeded directly then we will warn to use this here as
104+
# the Qiskit version is planned to be removed in a future version of Qiskit.
105+
warnings.warn(
106+
"Using random that is seeded via qiskit.utils algorithm_globals is deprecated "
107+
"since version 0.2.0. Instead set random_seed directly to "
108+
"qiskit_algorithms.utils algorithm_globals.",
109+
category=DeprecationWarning,
110+
stacklevel=2,
111+
)
112+
113+
return qiskit_globals.random
114+
115+
except ImportError:
116+
if self._random is None:
117+
self._random = np.random.default_rng(self._random_seed)
118+
return self._random
119+
120+
121+
# Global instance to be used as the entry point for globals.
122+
algorithm_globals = QiskitAlgorithmGlobals()

qiskit_algorithms/utils/validate_initial_point.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import numpy as np
2020

2121
from qiskit.circuit import QuantumCircuit
22-
from qiskit.utils import algorithm_globals
22+
from qiskit_algorithms.utils import algorithm_globals
2323

2424

2525
def validate_initial_point(

qiskit_algorithms/variational_algorithm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
2424
This component has some function that is normally random. If you want to reproduce behavior
2525
then you should set the random number generator seed in the algorithm_globals
26-
(``qiskit.utils.algorithm_globals.random_seed = seed``).
26+
(``qiskit_algorithms.utils.algorithm_globals.random_seed = seed``).
2727
"""
2828

2929
from __future__ import annotations

0 commit comments

Comments
 (0)