Skip to content

Commit e5cedce

Browse files
authored
Tensor docs plus Linting and Typing and Black oh my (#54)
* TENSOR: Apply black and enforce it * TENSOR: Add isort and pylint. Fix to pass then enforce * TENSOR: Variety of linked fixes: * Add mypy type checking * Update infrastructure for validating package * Fix doc tests and add more examples * DOCTEST: Add doctest automatically to regression * Fix existing failures * DOCTEST: Fix non-uniform array * DOCTEST: Fix precision errors in example * AUTOMATION: Add test directory otherwise only doctests run * TENSOR: Fix bad rebase from numpy fix
1 parent ceb2a91 commit e5cedce

File tree

14 files changed

+839
-528
lines changed

14 files changed

+839
-528
lines changed

.github/workflows/regression-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
# flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
3838
- name: Run tests
3939
run: |
40-
coverage run --source pyttb -m pytest
40+
coverage run --source pyttb -m pytest tests/
4141
coverage report
4242
- name: Upload coverage to Coveralls
4343
run: coveralls --service=github

conftest.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,13 @@
1010
def add_packages(doctest_namespace):
1111
doctest_namespace['np'] = numpy
1212
doctest_namespace['ttb'] = pyttb
13+
14+
15+
def pytest_addoption(parser):
16+
parser.addoption('--packaging', action='store_true', dest="packaging",
17+
default=False, help="enable slow packaging tests")
18+
19+
20+
def pytest_configure(config):
21+
if not config.option.packaging:
22+
setattr(config.option, 'markexpr', 'not packaging')

pyproject.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,33 @@ documentation = "https://pyttb.readthedocs.io"
3030
requires = ["setuptools>=61.0", "numpy", "numpy_groupies", "scipy", "wheel"]
3131
build-backend = "setuptools.build_meta"
3232

33+
[tool.isort]
34+
profile = "black"
35+
36+
[tool.pylint]
37+
# Play nice with black
38+
max-line-length = 88
39+
disable="fixme,too-many-lines"
40+
41+
[tool.pylint.basic]
42+
# To match MATLAB Tensortoolbox styles for clarity
43+
argument-naming-style = "any"
44+
class-naming-style = "any"
45+
variable-naming-style = "any"
46+
47+
[tool.pylint.design]
48+
# MATLAB Tensortoolbox interface
49+
max-public-methods = 40
50+
51+
[tool.mypy]
52+
warn_unused_configs = true
53+
plugins = "numpy.typing.mypy_plugin"
54+
55+
[[tool.mypy.overrides]]
56+
module = [
57+
"scipy",
58+
"scipy.sparse",
59+
"scipy.sparse.linalg",
60+
"numpy_groupies"
61+
]
62+
ignore_missing_imports = true

pytest.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
[pytest]
22
markers =
33
indevelopment: marks tests as in development, should not be run
4+
packaging: slow tests that check formatting over function
45

56
filterwarnings =
67
ignore:.*deprecated.*:
8+
9+
addopts = --doctest-modules pyttb

pyttb/cp_als.py

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# U.S. Government retains certain rights in this software.
44

55
import pyttb as ttb
6-
from .pyttb_utils import *
6+
from pyttb.pyttb_utils import *
77
import numpy as np
88

99
def cp_als(tensor, rank, stoptol=1e-4, maxiters=1000, dimorder=None,
@@ -51,54 +51,56 @@ def cp_als(tensor, rank, stoptol=1e-4, maxiters=1000, dimorder=None,
5151
5252
Example
5353
-------
54+
Random initialization causes slight pertubation in intermediate results.
55+
`...` is our place holder for these numeric values.
5456
Example using default values ("random" initialization):
5557
5658
>>> weights = np.array([1., 2.])
5759
>>> fm0 = np.array([[1., 2.], [3., 4.]])
5860
>>> fm1 = np.array([[5., 6.], [7., 8.]])
5961
>>> K = ttb.ktensor.from_data(weights, [fm0, fm1])
6062
>>> np.random.seed(1)
61-
>>> M, Minit, output = ttb.cp_als(K.full(), 2)
63+
>>> M, Minit, output = ttb.cp_als(K.full(), 2) # doctest: +ELLIPSIS
6264
CP_ALS:
63-
Iter 0: f = 0.9999999836180988 f-delta = 0.9999999836180988
64-
Iter 1: f = 0.9999999836180988 f-delta = 0.0
65-
Final f = 0.9999999836180988
66-
>>> print(M)
65+
Iter 0: f = ... f-delta = ...
66+
Iter 1: f = ... f-delta = ...
67+
Final f = ...
68+
>>> print(M) # doctest: +ELLIPSIS
6769
ktensor of shape 2 x 2
68-
weights=[108.47158396 8.61141076]
70+
weights=[108.4715... 8.6114...]
6971
factor_matrices[0] =
70-
[[0.41877462 0.39899343]
71-
[0.9080902 0.91695378]]
72+
[[0.4187... 0.3989...]
73+
[0.9080... 0.9169...]]
7274
factor_matrices[1] =
73-
[[0.61888633 0.25815611]
74-
[0.78548056 0.96610322]]
75-
>>> print(Minit)
75+
[[0.6188... 0.2581...]
76+
[0.7854... 0.9661...]]
77+
>>> print(Minit) # doctest: +ELLIPSIS
7678
ktensor of shape 2 x 2
7779
weights=[1. 1.]
7880
factor_matrices[0] =
79-
[[4.17022005e-01 7.20324493e-01]
80-
[1.14374817e-04 3.02332573e-01]]
81+
[[4.1702...e-01 7.2032...e-01]
82+
[1.1437...e-04 3.0233...e-01]]
8183
factor_matrices[1] =
82-
[[0.14675589 0.09233859]
83-
[0.18626021 0.34556073]]
84+
[[0.1467... 0.0923...]
85+
[0.1862... 0.3455...]]
8486
>>> print(output)
85-
{'params': (0.0001, 1000, 1, [0, 1]), 'iters': 1, 'normresidual': 1.9073486328125e-06, 'fit': 0.9999999836180988}
87+
{'params': (0.0001, 1000, 1, [0, 1]), 'iters': 1, 'normresidual': ..., 'fit': ...}
8688
8789
Example using "nvecs" initialization:
8890
89-
>>> M, Minit, output = ttb.cp_als(K.full(), 2, init="nvecs")
91+
>>> M, Minit, output = ttb.cp_als(K.full(), 2, init="nvecs") # doctest: +ELLIPSIS
9092
CP_ALS:
91-
Iter 0: f = 1.0 f-delta = 1.0
92-
Iter 1: f = 1.0 f-delta = 0.0
93-
Final f = 1.0
93+
Iter 0: f = ... f-delta = ...
94+
Iter 1: f = ... f-delta = ...
95+
Final f = ...
9496
9597
Example using :class:`pyttb.ktensor` initialization:
9698
97-
>>> M, Minit, output = ttb.cp_als(K.full(), 2, init=K)
99+
>>> M, Minit, output = ttb.cp_als(K.full(), 2, init=K) # doctest: +ELLIPSIS
98100
CP_ALS:
99-
Iter 0: f = 0.9999999836180988 f-delta = 0.9999999836180988
100-
Iter 1: f = 0.9999999836180988 f-delta = 0.0
101-
Final f = 0.9999999836180988
101+
Iter 0: f = ... f-delta = ...
102+
Iter 1: f = ... f-delta = ...
103+
Final f = ...
102104
"""
103105

104106
# Extract number of dimensions and norm of tensor
@@ -246,5 +248,5 @@ def cp_als(tensor, rank, stoptol=1e-4, maxiters=1000, dimorder=None,
246248

247249
if __name__ == "__main__":
248250
import doctest # pragma: no cover
249-
import pyttb as ttb # pragma: no cover
251+
250252
doctest.testmod() # pragma: no cover

pyttb/khatrirao.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ def khatrirao(*listOfMatrices, reverse=False):
2424
2525
Examples
2626
--------
27-
>>>A = np.random.norm(size=(5,2))
28-
>>>khatrirao(A,B) #<-- Khatri-Rao of A and B
29-
>>>>khatrirao(B,A,reverse=True) #<-- same thing as above
30-
>>>>khatrirao([A,A,B]) #<-- passing a list
31-
>>>>khatrirao([B,A,A},reverse = True) #<-- same as above
27+
>>> A = np.random.normal(size=(5,2))
28+
>>> B = np.random.normal(size=(5,2))
29+
>>> _ = khatrirao(A,B) #<-- Khatri-Rao of A and B
30+
>>> _ = khatrirao(B,A,reverse=True) #<-- same thing as above
31+
>>> _ = khatrirao([A,A,B]) #<-- passing a list
32+
>>> _ = khatrirao([B,A,A],reverse = True) #<-- same as above
3233
"""
3334
#Determine if list of matrices of multiple matrix arguments
3435
if isinstance(listOfMatrices[0], list):

0 commit comments

Comments
 (0)