Skip to content

Commit 5346dfa

Browse files
committed
Merge branch 'master' into feature/small_improvements
2 parents e34515b + d7f380b commit 5346dfa

File tree

12 files changed

+70
-134
lines changed

12 files changed

+70
-134
lines changed

.readthedocs.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ python:
1616
- doc
1717
- plotting
1818
- bloch_sphere_visualization
19-
- fancy_progressbar
2019

2120
sphinx:
2221
builder: html

doc/source/api.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
API
2+
===
3+
4+
.. autosummary::
5+
:toctree: generated
6+
:recursive:
7+
8+
filter_functions

doc/source/conf.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,28 @@
3838
'nbsphinx',
3939
'sphinx.ext.mathjax',
4040
'sphinx.ext.todo',
41+
'sphinx.ext.autodoc',
4142
'sphinx.ext.autosummary',
4243
'numpydoc',
4344
'sphinx.ext.extlinks',
4445
'sphinx.ext.viewcode',
4546
'sphinx.ext.ifconfig',
4647
'sphinx.ext.napoleon',
4748
'sphinx.ext.intersphinx',
48-
#'sphinxcontrib.apidoc',
49+
'sphinxcontrib.apidoc',
4950
#'IPython.sphinxext.ipython_console_highlighting',
5051
#'IPython.sphinxext.ipython_directive',
5152
#'matplotlib.sphinxext.only_directives',
5253
#'matplotlib.sphinxext.plot_directive',
5354
#'matplotlib.sphinxext.mathmpl',
54-
#'sphinx.ext.autodoc',
5555
#'sphinx.ext.doctest',
5656
]
5757

5858
# Apidoc config
5959
apidoc_module_dir = '../../filter_functions'
6060
apidoc_excluded_paths = ['../tests']
6161
apidoc_separate_modules = True
62+
apidoc_module_first = True
6263

6364
# Numpydoc settings
6465
numpydoc_show_inherited_class_members = False

doc/source/filter_functions.rst

Lines changed: 0 additions & 85 deletions
This file was deleted.

doc/source/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Documentation
2323
:numbered:
2424

2525
examples/examples
26-
filter_functions API Documentation <filter_functions>
26+
filter_functions API Documentation <api>
2727

2828
Indices and tables
2929
==================

environment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
name: filter_functions
22

33
channels:
4-
- defaults
54
- conda-forge
65

76
dependencies:
87
- python >= 3.9
98
- qutip
9+
- pandoc
1010
- pip
1111

1212
prefix: /home/docs/.conda/envs/filter_functions

filter_functions/basis.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import numpy as np
4848
import opt_einsum as oe
4949
from numpy import linalg as nla
50-
from numpy.core import ndarray
5150
from scipy import linalg as sla
5251
from sparse import COO
5352

@@ -56,7 +55,7 @@
5655
__all__ = ['Basis', 'expand', 'ggm_expand', 'normalize']
5756

5857

59-
class Basis(ndarray):
58+
class Basis(np.ndarray):
6059
r"""
6160
Class for operator bases. There are several ways to instantiate a
6261
Basis object:
@@ -211,22 +210,26 @@ def __eq__(self, other: object) -> bool:
211210
# Not ndarray
212211
return np.equal(self, other)
213212

214-
return np.allclose(self.view(ndarray), other.view(ndarray),
213+
return np.allclose(self.view(np.ndarray), other.view(np.ndarray),
215214
atol=self._atol, rtol=self._rtol)
216215

217-
def __contains__(self, item: ndarray) -> bool:
216+
def __contains__(self, item: np.ndarray) -> bool:
218217
"""Implement 'in' operator."""
219-
return any(np.isclose(item.view(ndarray), self.view(ndarray),
218+
return any(np.isclose(item.view(np.ndarray), self.view(np.ndarray),
220219
rtol=self._rtol, atol=self._atol).all(axis=(1, 2)))
221220

222-
def __array_wrap__(self, out_arr, context=None):
221+
def __array_wrap__(self, arr, context=None, return_scalar=False):
223222
"""
224223
Fixes problem that ufuncs return 0-d arrays instead of scalars.
225224
226225
https://github.com/numpy/numpy/issues/5819#issue-72454838
227226
"""
228-
if out_arr.ndim:
229-
return ndarray.__array_wrap__(self, out_arr, context)
227+
try:
228+
return super().__array_wrap__(arr, context, return_scalar=True)
229+
except TypeError:
230+
if arr.ndim:
231+
# Numpy < 2
232+
return np.ndarray.__array_wrap__(self, arr, context)
230233

231234
def _print_checks(self) -> None:
232235
"""Print checks for debug purposes."""
@@ -595,7 +598,7 @@ def _full_from_partial(elems: Sequence, traceless: bool, labels: Sequence[str])
595598
# sort Identity label to the front, default to first if not found
596599
# (should not happen since traceless checks that it is present)
597600
id_idx = next((i for i, elem in enumerate(elems)
598-
if np.allclose(Id.view(ndarray), elem.view(ndarray),
601+
if np.allclose(Id.view(np.ndarray), elem.view(np.ndarray),
599602
rtol=elems._rtol, atol=elems._atol)), 0)
600603
labels.insert(0, labels.pop(id_idx))
601604

@@ -604,7 +607,7 @@ def _full_from_partial(elems: Sequence, traceless: bool, labels: Sequence[str])
604607
return basis, labels
605608

606609

607-
def _norm(b: Sequence) -> ndarray:
610+
def _norm(b: Sequence) -> np.ndarray:
608611
"""Frobenius norm with two singleton dimensions inserted at the end."""
609612
b = np.asanyarray(b)
610613
norm = nla.norm(b, axis=(-1, -2))
@@ -631,8 +634,8 @@ def normalize(b: Basis) -> Basis:
631634
return (b/_norm(b)).squeeze().view(Basis)
632635

633636

634-
def expand(M: Union[ndarray, Basis], basis: Union[ndarray, Basis],
635-
normalized: bool = True, hermitian: bool = False, tidyup: bool = False) -> ndarray:
637+
def expand(M: Union[np.ndarray, Basis], basis: Union[np.ndarray, Basis],
638+
normalized: bool = True, hermitian: bool = False, tidyup: bool = False) -> np.ndarray:
636639
r"""
637640
Expand the array *M* in the basis given by *basis*.
638641
@@ -682,7 +685,7 @@ def cast(arr):
682685
return util.remove_float_errors(coefficients) if tidyup else coefficients
683686

684687

685-
def ggm_expand(M: Union[ndarray, Basis], traceless: bool = False,
688+
def ggm_expand(M: Union[np.ndarray, Basis], traceless: bool = False,
686689
hermitian: bool = False, tidyup: bool = False) -> ndarray:
687690
r"""
688691
Expand the matrix *M* in a Generalized Gell-Mann basis [Bert08]_.
@@ -771,7 +774,7 @@ def cast(arr):
771774
return coeffs
772775

773776

774-
def equivalent_pauli_basis_elements(idx: Union[Sequence[int], int], N: int) -> ndarray:
777+
def equivalent_pauli_basis_elements(idx: Union[Sequence[int], int], N: int) -> np.ndarray:
775778
"""
776779
Get the indices of the equivalent (up to identities tensored to it)
777780
basis elements of Pauli bases of qubits at position idx in the total
@@ -784,7 +787,7 @@ def equivalent_pauli_basis_elements(idx: Union[Sequence[int], int], N: int) -> n
784787
return elem_idx
785788

786789

787-
def remap_pauli_basis_elements(order: Sequence[int], N: int) -> ndarray:
790+
def remap_pauli_basis_elements(order: Sequence[int], N: int) -> np.ndarray:
788791
"""
789792
For a N-qubit Pauli basis, transpose the order of the subsystems and
790793
return the indices that permute the old basis to the new.

filter_functions/util.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
2626
:func:`abs2`
2727
Absolute value squared
2828
:func:`get_indices_from_identifiers`
29-
The the indices of a subset of identifiers within a list of
30-
identifiers.
29+
The indices of a subset of identifiers within a list of identifiers.
3130
:func:`tensor`
3231
Fast, flexible tensor product of an arbitrary number of inputs using
3332
:func:`~numpy.einsum`
@@ -70,6 +69,7 @@
7069
import functools
7170
import inspect
7271
import operator
72+
import os
7373
import string
7474
from itertools import zip_longest
7575
from typing import Callable, Iterable, List, Optional, Sequence, Tuple, Union
@@ -79,17 +79,25 @@
7979

8080
from .types import Operator, State
8181

82-
try:
83-
import ipynbname
84-
_NOTEBOOK_NAME = ipynbname.name()
85-
except (ImportError, IndexError, FileNotFoundError):
86-
_NOTEBOOK_NAME = ''
8782

88-
if _NOTEBOOK_NAME:
89-
from tqdm.notebook import tqdm as _tqdm
83+
def _in_notebook_kernel():
84+
# https://github.com/jupyterlab/jupyterlab/issues/16282
85+
return 'JPY_SESSION_NAME' in os.environ and os.environ['JPY_SESSION_NAME'].endswith('.ipynb')
86+
87+
88+
def _in_jupyter_kernel():
89+
# https://discourse.jupyter.org/t/how-to-know-from-python-script-if-we-are-in-jupyterlab/23993
90+
return 'JPY_PARENT_PID' in os.environ
91+
92+
93+
if not _in_notebook_kernel():
94+
if _in_jupyter_kernel():
95+
# (10/24) Autonotebook gets confused in jupyter consoles
96+
from tqdm.std import tqdm
97+
else:
98+
from tqdm.autonotebook import tqdm
9099
else:
91-
# Either not running notebook or not able to determine
92-
from tqdm import tqdm as _tqdm
100+
from tqdm.notebook import tqdm
93101

94102
__all__ = ['paulis', 'abs2', 'all_array_equal', 'dot_HS', 'get_sample_frequencies',
95103
'hash_array_along_axis', 'mdot', 'oper_equiv', 'progressbar', 'remove_float_errors',
@@ -1067,7 +1075,7 @@ def progressbar(iterable: Iterable, *args, **kwargs):
10671075
for i in progressbar(range(10)):
10681076
do_something()
10691077
"""
1070-
return _tqdm(iterable, *args, **kwargs)
1078+
return tqdm(iterable, *args, **kwargs)
10711079

10721080

10731081
def progressbar_range(*args, show_progressbar: bool = True, **kwargs):

setup.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ def extract_version(version_file):
1818

1919
extras_require = {'plotting': ['matplotlib'],
2020
'bloch_sphere_visualization': ['qutip', 'matplotlib'],
21-
'fancy_progressbar': ['ipynbname', 'jupyter'],
2221
'doc': ['jupyter', 'nbsphinx', 'numpydoc', 'sphinx', 'sphinx_rtd_theme',
23-
'ipympl', 'qutip-qip', 'qutip-qtrl'],
22+
'sphinxcontrib-apidoc', 'ipympl', 'qutip-qip', 'qutip-qtrl', 'numpy<2'],
2423
'tests': ['pytest>=4.6', 'pytest-cov', 'codecov']}
2524

2625
extras_require['all'] = list({dep for deps in extras_require.values() for dep in deps})

tests/test_basis.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from copy import copy
2525
from itertools import product
2626

27+
import filter_functions as ff
2728
import numpy as np
2829
import pytest
2930
from opt_einsum import contract
@@ -153,9 +154,21 @@ def test_basis_properties(self):
153154

154155
base._print_checks()
155156

156-
basis = util.paulis[1].view(ff.Basis)
157-
self.assertTrue(basis.isorthonorm)
158-
self.assertArrayEqual(basis.T, basis.view(np.ndarray).T)
157+
# single element always considered orthonormal
158+
orthonorm = rng.normal(size=(d, d))
159+
self.assertTrue(orthonorm.view(ff.Basis).isorthonorm)
160+
161+
herm = testutil.rand_herm(d).squeeze()
162+
self.assertTrue(herm.view(ff.Basis).isherm)
163+
164+
herm[0, 1] += 1
165+
self.assertFalse(herm.view(ff.Basis).isherm)
166+
167+
traceless = testutil.rand_herm_traceless(d).squeeze()
168+
self.assertTrue(traceless.view(ff.Basis).istraceless)
169+
170+
traceless[0, 0] += 1
171+
self.assertFalse(traceless.view(ff.Basis).istraceless)
159172

160173
def test_transpose(self):
161174
arr = rng.normal(size=(2, 3, 3))

0 commit comments

Comments
 (0)