Skip to content

Commit 812c1f4

Browse files
nickjntjohnson1
nickj
authored andcommitted
DOCTEST: Add doctest automatically to regression
* Fix existing failures
1 parent 7381efd commit 812c1f4

File tree

8 files changed

+137
-134
lines changed

8 files changed

+137
-134
lines changed

pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ markers =
55

66
filterwarnings =
77
ignore:.*deprecated.*:
8+
9+
addopts = --doctest-modules pyttb

pyttb/cp_als.py

Lines changed: 27 additions & 25 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)
8587
{'params': (0.0001, 1000, 1, [0, 1]), 'iters': 1, 'normresidual': 1.9073486328125e-06, 'fit': 0.9999999836180988}
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):

pyttb/ktensor.py

Lines changed: 72 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from __future__ import annotations
77

88
import pyttb as ttb
9-
from .pyttb_utils import *
9+
from pyttb.pyttb_utils import *
1010
import numpy as np
1111
import warnings
1212
import scipy.sparse as sparse
@@ -267,21 +267,21 @@ def from_function(cls, fun, shape, num_components):
267267
268268
>>> np.random.seed(1)
269269
>>> K_random = ttb.ktensor.from_function(np.random.random_sample, (2, 3, 4), 2)
270-
>>> print(K_random)
270+
>>> print(K_random) # doctest: +ELLIPSIS
271271
ktensor of shape 2 x 3 x 4
272272
weights=[1. 1.]
273273
factor_matrices[0] =
274-
[[4.17022005e-01 7.20324493e-01]
275-
[1.14374817e-04 3.02332573e-01]]
274+
[[4.1702...e-01 7.2032...e-01]
275+
[1.1437...e-04 3.0233...e-01]]
276276
factor_matrices[1] =
277-
[[0.14675589 0.09233859]
278-
[0.18626021 0.34556073]
279-
[0.39676747 0.53881673]]
277+
[[0.1467... 0.0923...]
278+
[0.1862... 0.3455...]
279+
[0.3967... 0.5388...]]
280280
factor_matrices[2] =
281-
[[0.41919451 0.6852195 ]
282-
[0.20445225 0.87811744]
283-
[0.02738759 0.67046751]
284-
[0.4173048 0.55868983]]
281+
[[0.4191... 0.6852...]
282+
[0.2044... 0.8781...]
283+
[0.0273... 0.6704...]
284+
[0.4173... 0.5586...]]
285285
286286
Create a `ktensor` with entries equal to 1:
287287
@@ -529,41 +529,41 @@ def copy(self):
529529
530530
>>> np.random.seed(1)
531531
>>> K = ttb.ktensor.from_function(np.random.random_sample, (2, 3, 4), 2)
532-
>>> print(K)
532+
>>> print(K) # doctest: +ELLIPSIS
533533
ktensor of shape 2 x 3 x 4
534534
weights=[1. 1.]
535535
factor_matrices[0] =
536-
[[4.17022005e-01 7.20324493e-01]
537-
[1.14374817e-04 3.02332573e-01]]
536+
[[4.1702...e-01 7.2032...e-01]
537+
[1.1437...e-04 3.0233...e-01]]
538538
factor_matrices[1] =
539-
[[0.14675589 0.09233859]
540-
[0.18626021 0.34556073]
541-
[0.39676747 0.53881673]]
539+
[[0.1467... 0.0923...]
540+
[0.1862... 0.3455...]
541+
[0.3967... 0.5388...]]
542542
factor_matrices[2] =
543-
[[0.41919451 0.6852195 ]
544-
[0.20445225 0.87811744]
545-
[0.02738759 0.67046751]
546-
[0.4173048 0.55868983]]
543+
[[0.4191... 0.6852...]
544+
[0.2044... 0.8781...]
545+
[0.0273... 0.6704...]
546+
[0.4173... 0.5586...]]
547547
548548
Create a copy of the `ktensor` and change the weights:
549549
550550
>>> K1 = K.copy()
551551
>>> K1.weights = np.array([2., 3.])
552-
>>> print(K1)
552+
>>> print(K1) # doctest: +ELLIPSIS
553553
ktensor of shape 2 x 3 x 4
554554
weights=[2. 3.]
555555
factor_matrices[0] =
556-
[[4.17022005e-01 7.20324493e-01]
557-
[1.14374817e-04 3.02332573e-01]]
556+
[[4.1702...e-01 7.2032...e-01]
557+
[1.1437...e-04 3.023...e-01]]
558558
factor_matrices[1] =
559-
[[0.14675589 0.09233859]
560-
[0.18626021 0.34556073]
561-
[0.39676747 0.53881673]]
559+
[[0.1467... 0.0923...]
560+
[0.1862... 0.3455...]
561+
[0.3967... 0.5388...]]
562562
factor_matrices[2] =
563-
[[0.41919451 0.6852195 ]
564-
[0.20445225 0.87811744]
565-
[0.02738759 0.67046751]
566-
[0.4173048 0.55868983]]
563+
[[0.4191... 0.6852...]
564+
[0.2044... 0.8781...]
565+
[0.0273... 0.6704...]
566+
[0.4173... 0.5586...]]
567567
"""
568568
return ttb.ktensor.from_tensor_type(self)
569569

@@ -743,15 +743,15 @@ def fixsigns(self, other=None):
743743
>>> K2.factor_matrices[0][1, 1] = - K2.factor_matrices[0][1, 1]
744744
>>> K2.factor_matrices[1][1, 1] = - K2.factor_matrices[1][1, 1]
745745
>>> K = K.fixsigns(K2)
746-
>>> print(K)
746+
>>> print(K) # doctest: +ELLIPSIS
747747
ktensor of shape 2 x 2
748-
weights=[27.20294102 89.4427191 ]
748+
weights=[27.2029... 89.4427...]
749749
factor_matrices[0] =
750-
[[ 0.31622777 -0.4472136 ]
751-
[ 0.9486833 -0.89442719]]
750+
[[ 0.3162... -0.4472...]
751+
[ 0.9486... -0.8944...]]
752752
factor_matrices[1] =
753-
[[ 0.58123819 -0.6 ]
754-
[ 0.81373347 -0.8 ]]
753+
[[ 0.5812... -0.6...]
754+
[ 0.8137... -0.8...]]
755755
"""
756756
if other == None:
757757
for r in range(self.ncomponents):
@@ -842,6 +842,7 @@ def full(self):
842842
data[:, :] =
843843
[[29. 39.]
844844
[63. 85.]]
845+
<BLANKLINE>
845846
"""
846847
data = self.weights @ ttb.khatrirao(self.factor_matrices, reverse=True).T
847848
return ttb.tensor.from_data(data, self.shape)
@@ -993,8 +994,8 @@ def mask(self, W):
993994
994995
>>> W = ttb.tensor.from_data(np.array([[0, 1], [1, 0]]))
995996
>>> print(K.mask(W))
996-
[[39.]
997-
[63.]]
997+
[[63.]
998+
[39.]]
998999
"""
9991000
# Error check
10001001
if len(W.shape) != len(self.shape) or np.any(np.array(W.shape) > np.array(self.shape)):
@@ -1123,16 +1124,16 @@ def normalize(self, weight_factor=None, sort=False, normtype=2, mode=None):
11231124
Example
11241125
-------
11251126
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2)
1126-
>>> print(K.normalize())
1127+
>>> print(K.normalize()) # doctest: +ELLIPSIS
11271128
ktensor of shape 2 x 3 x 4
1128-
weights=[4.89897949 4.89897949]
1129+
weights=[4.898... 4.898...]
11291130
factor_matrices[0] =
1130-
[[0.70710678 0.70710678]
1131-
[0.70710678 0.70710678]]
1131+
[[0.7071... 0.7071...]
1132+
[0.7071... 0.7071...]]
11321133
factor_matrices[1] =
1133-
[[0.57735027 0.57735027]
1134-
[0.57735027 0.57735027]
1135-
[0.57735027 0.57735027]]
1134+
[[0.5773... 0.5773...]
1135+
[0.5773... 0.5773...]
1136+
[0.5773... 0.5773...]]
11361137
factor_matrices[2] =
11371138
[[0.5 0.5]
11381139
[0.5 0.5]
@@ -1215,16 +1216,16 @@ def nvecs(self, n, r, flipsign=True):
12151216
12161217
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2)
12171218
>>> nvecs1 = K.nvecs(0, 1)
1218-
>>> print(nvecs1)
1219-
[[0.70710678]
1220-
[0.70710678]]
1219+
>>> print(nvecs1) # doctest: +ELLIPSIS
1220+
[[0.70710678...]
1221+
[0.70710678...]]
12211222
12221223
Compute first 2 leading eigenvectors for dimension 0:
12231224
12241225
>>> nvecs2 = K.nvecs(0, 2)
1225-
>>> print(nvecs2)
1226-
[[ 0.70710678 0.70710678]
1227-
[ 0.70710678 -0.70710678]]
1226+
>>> print(nvecs2) # doctest: +ELLIPSIS
1227+
[[ 0.70710678... 0.70710678...]
1228+
[ 0.70710678... -0.70710678...]]
12281229
"""
12291230
M = self.weights[:, None] @ self.weights[:, None].T
12301231
for i in range(self.ndims):
@@ -1410,12 +1411,9 @@ def score(self, other, weight_penalty=True, threshold=0.99, greedy=True):
14101411
-------
14111412
Create two `ktensor` instances:
14121413
1413-
>>> A = ttb.ktensor.from_data(np.array([2, 1, 3]), np.ones((3,3)), np.ones((4,3)), np.ones((5,3)))
1414-
>>> B = ttb.ktensor.from_data(np.array([2, 4]), np.ones((3,2)), np.ones((4,2)), np.ones((5,2)))
1415-
1416-
Compute `score` using `ktensor.weights`:
1417-
1418-
>>> score,Aperm,flag,perm = A.score(B)
1414+
>>> A = ttb.ktensor.from_data(np.array([2., 1., 3.]), np.ones((3,3)), np.ones((4,3)), np.ones((5,3)))
1415+
>>> B = ttb.ktensor.from_data(np.array([2., 4.]), np.ones((3,2)), np.ones((4,2)), np.ones((5,2)))
1416+
>>> score,Aperm,flag,perm = A.score(B) # Compute `score` using `ktensor.weights`
14191417
>>> print(score)
14201418
0.875
14211419
>>> print(perm)
@@ -1531,15 +1529,15 @@ def symmetrize(self):
15311529
Make the factor matrices of the `ktensor` symmetric:
15321530
15331531
>>> K1 = K.symmetrize()
1534-
>>> print(K1)
1532+
>>> print(K1) # doctest: +ELLIPSIS
15351533
ktensor of shape 2 x 2
15361534
weights=[1. 1.]
15371535
factor_matrices[0] =
1538-
[[2.34043142 4.95196735]
1539-
[4.59606911 8.01245149]]
1536+
[[2.3404... 4.9519...]
1537+
[4.5960... 8.0124...]]
15401538
factor_matrices[1] =
1541-
[[2.34043142 4.95196735]
1542-
[4.59606911 8.01245149]]
1539+
[[2.3404... 4.9519...]
1540+
[4.5960... 8.0124...]]
15431541
"""
15441542
# Check tensor dimensions for compatibility with symmetrization
15451543
assert (self.shape == self.shape[0]*np.ones(self.ndims)).all(), "Tensor is not cubic -- cannot be symmetrized"
@@ -1607,20 +1605,20 @@ def tolist(self, mode=None):
16071605
Spread weights equally to all factors and return list of factor matrices:
16081606
16091607
>>> fm_list = K.tolist()
1610-
>>> for fm in fm_list: print(fm)
1611-
[[1. 2.82842712]
1612-
[3. 5.65685425]]
1613-
[[ 5. 8.48528137]
1614-
[ 7. 11.3137085 ]]
1608+
>>> for fm in fm_list: print(fm) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
1609+
[[1. 2.8284...]
1610+
[3. 5.6568...]]
1611+
[[ 5. 8.4852...]
1612+
[ 7. 11.313...]]
16151613
16161614
Shift weight to single factor matrix and return list of factor matrices:
16171615
16181616
>>> fm_list = K.tolist(0)
1619-
>>> for fm in fm_list: print(fm)
1620-
[[ 8.60232527 40. ]
1621-
[25.8069758 80. ]]
1622-
[[0.58123819 0.6 ]
1623-
[0.81373347 0.8 ]]
1617+
>>> for fm in fm_list: print(fm) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
1618+
[[ 8.6023... 40. ]
1619+
[25.8069... 80. ]]
1620+
[[0.5812... 0.6...]
1621+
[0.8137... 0.8...]]
16241622
"""
16251623
if mode is not None:
16261624
if isinstance(mode, int) and mode in range(self.ndims):
@@ -2167,5 +2165,5 @@ def __repr__(self):
21672165

21682166
if __name__ == "__main__":
21692167
import doctest # pragma: no cover
2170-
import pyttb as ttb # pragma: no cover
2168+
21712169
doctest.testmod() # pragma: no cover

0 commit comments

Comments
 (0)