Skip to content

Commit c3249ad

Browse files
authored
Nick/link check (#359)
* Internal: Try new link checker * Internal: Add codespell and fix typos. * Internal: See if codespell precommit finds config. * Internal: Found config. Now enable reading it Closes #358
1 parent 589239b commit c3249ad

31 files changed

+114
-64
lines changed

.github/workflows/markdown-check.yml

+9-3
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ on:
77
branches: [ "main" ]
88

99
jobs:
10-
markdown-link-check:
10+
check-links:
11+
name: runner / linkspector
1112
runs-on: ubuntu-latest
1213
steps:
13-
- uses: actions/checkout@v4
14-
- uses: gaurav-nelson/github-action-markdown-link-check@v1
14+
- uses: actions/checkout@v4
15+
- name: Run linkspector
16+
uses: umbrelladocs/action-linkspector@v1
17+
with:
18+
github_token: ${{ secrets.github_token }}
19+
reporter: github-pr-review
20+
fail_on_error: true

.pre-commit-config.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,10 @@ repos:
1313
--extra-keys=metadata.language_info metadata.vscode metadata.kernelspec cell.metadata.vscode,
1414
--drop-empty-cells
1515
]
16+
- repo: https://github.com/codespell-project/codespell
17+
rev: v2.3.0
18+
hooks:
19+
- id: codespell
20+
args: [ --toml, "pyproject.toml"]
21+
additional_dependencies:
22+
- tomli

CHANGELOG.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
- Aligning comparison operator output for data classes (https://github.com/sandialabs/pyttb/pull/331)
1313
- Improved:
1414
- Getting starting documentation (https://github.com/sandialabs/pyttb/pull/324)
15-
- Development enviroment (https://github.com/sandialabs/pyttb/pull/329, https://github.com/sandialabs/pyttb/pull/330)
15+
- Development environment (https://github.com/sandialabs/pyttb/pull/329, https://github.com/sandialabs/pyttb/pull/330)
1616
- Documentation (https://github.com/sandialabs/pyttb/pull/328, https://github.com/sandialabs/pyttb/pull/334)
1717

1818
# v1.8.0 (2024-10-23)
@@ -93,7 +93,7 @@
9393
- Addresses ambiguity of -0 by using `exclude_dims` (`numpy.ndarray`) parameter
9494
- `ktensor.ttv`, `sptensor.ttv`, `tensor.ttv`, `ttensor.ttv`
9595
- Use `exlude_dims` parameter instead of `-dims`
96-
- Explicit nameing of dimensions to exclude
96+
- Explicit naming of dimensions to exclude
9797
- `tensor.ttsv`
9898
- Use `skip_dim` (`int`) parameter instead of `-dims`
9999
- Exclude all dimensions up to and including `skip_dim`

CONTRIBUTING.md

+11-5
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,25 @@ current or filing a new [issue](https://github.com/sandialabs/pyttb/issues).
3535
```
3636
git checkout -b my-new-feature-branch
3737
```
38-
1. Formatters and linting
38+
1. Formatters and linting (These are checked in the full test suite as well)
3939
1. Run autoformatters and linting from root of project (they will change your code)
40-
```commandline
41-
ruff check . --fix
42-
ruff format
43-
```
40+
```commandline
41+
ruff check . --fix
42+
ruff format
43+
```
4444
1. Ruff's `--fix` won't necessarily address everything and may point out issues that need manual attention
4545
1. [We](./.pre-commit-config.yaml) optionally support [pre-commit hooks](https://pre-commit.com/) for this
4646
1. Alternatively, you can run `pre-commit run --all-files` from the command line if you don't want to install the hooks.
4747
1. Check typing
4848
```commandline
4949
mypy pyttb/
5050
```
51+
1. Not included in our pre-commit hooks because of slow runtime.
52+
1. Check spelling
53+
```commandline
54+
codespell
55+
```
56+
1. This is also included in the optional pre-commit hooks.
5157
5258
1. Run tests (at desired fidelity)
5359
1. Just doctests (enabled by default)

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ low-rank tensor decompositions:
3232
[`cp_apr`](https://pyttb.readthedocs.io/en/stable/cpapr.html "CP decomposition via Alternating Poisson Regression"),
3333
[`gcp_opt`](https://pyttb.readthedocs.io/en/stable/gcpopt.html "Generalized CP decomposition"),
3434
[`hosvd`](https://pyttb.readthedocs.io/en/stable/hosvd.html "Tucker decomposition via Higher Order Singular Value Decomposition"),
35-
[`tucker_als`](https://pyttb.readthedocs.io/en/stable/tuckerals.html "Tucker decompostion via Alternating Least Squares")
35+
[`tucker_als`](https://pyttb.readthedocs.io/en/stable/tuckerals.html "Tucker decomposition via Alternating Least Squares")
3636

3737
## Quick Start
3838

docs/source/tutorial/algorithm_cp_als.ipynb

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@
122122
"cell_type": "markdown",
123123
"metadata": {},
124124
"source": [
125-
"## Increase the maximium number of iterations\n",
125+
"## Increase the maximum number of iterations\n",
126126
"Note that the previous run kicked out at only 10 iterations, before reaching the specified convegence tolerance. Let's increase the maximum number of iterations and try again, using the same initial guess."
127127
]
128128
},
@@ -337,7 +337,7 @@
337337
"source": [
338338
"## Recommendations\n",
339339
"* Run multiple times with different guesses and select the solution with the best fit.\n",
340-
"* Try different ranks and choose the solution that is the best descriptor for your data based on the combination of the fit and the interpretaton of the factors, e.g., by visualizing the results."
340+
"* Try different ranks and choose the solution that is the best descriptor for your data based on the combination of the fit and the interpretation of the factors, e.g., by visualizing the results."
341341
]
342342
}
343343
],

docs/source/tutorial/algorithm_gcp_opt.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"tags": []
2020
},
2121
"source": [
22-
"This document outlines usage and examples for the generalized CP (GCP) tensor decomposition implmented in `pyttb.gcp_opt`. GCP allows alternate objective functions besides sum of squared errors, which is the standard for CP. The code support both dense and sparse input tensors, but the sparse input tensors require randomized optimization methods.\n",
22+
"This document outlines usage and examples for the generalized CP (GCP) tensor decomposition implemented in `pyttb.gcp_opt`. GCP allows alternate objective functions besides sum of squared errors, which is the standard for CP. The code support both dense and sparse input tensors, but the sparse input tensors require randomized optimization methods.\n",
2323
"\n",
2424
"GCP is described in greater detail in the manuscripts:\n",
2525
"* D. Hong, T. G. Kolda, J. A. Duersch, Generalized Canonical Polyadic Tensor Decomposition, SIAM Review, 62:133-163, 2020, https://doi.org/10.1137/18M1203626\n",

docs/source/tutorial/algorithm_hosvd.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
"metadata": {},
9595
"source": [
9696
"## Generate a core with different accuracies for different shapes\n",
97-
"We will create a core `tensor` that has is nearly block diagonal. The blocks are expontentially decreasing in norm, with the idea that we can pick off one block at a time as we increate the prescribed accuracy of the HOSVD. To do this, we define and use a function `tenrandblk()`."
97+
"We will create a core `tensor` that has is nearly block diagonal. The blocks are expontentially decreasing in norm, with the idea that we can pick off one block at a time as we increase the prescribed accuracy of the HOSVD. To do this, we define and use a function `tenrandblk()`."
9898
]
9999
},
100100
{

docs/source/tutorial/class_sptensor.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"metadata": {},
1818
"source": [
1919
"## Creating a `sptensor`\n",
20-
"The `sptensor` class stores the data in coordinate format. A sparse `sptensor` can be created by passing in a list of subscripts and values. For example, here we pass in three subscripts and a scalar value. The resuling sparse `sptensor` has three nonzero entries, and the `shape` is the size of the largest subscript in each dimension."
20+
"The `sptensor` class stores the data in coordinate format. A sparse `sptensor` can be created by passing in a list of subscripts and values. For example, here we pass in three subscripts and a scalar value. The resulting sparse `sptensor` has three nonzero entries, and the `shape` is the size of the largest subscript in each dimension."
2121
]
2222
},
2323
{

docs/source/tutorial/class_sumtensor.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"metadata": {},
5555
"source": [
5656
"## Creating sumtensors\n",
57-
"A sumtensor `T` can only be delared as a sum of same-shaped tensors T1, T2,...,TN. The summand tensors are stored internally, which define the \"parts\" of the `sumtensor`. The parts of a `sumtensor` can be (dense) tensors (`tensor`), sparse tensors (` sptensor`), Kruskal tensors (`ktensor`), or Tucker tensors (`ttensor`). An example of the use of the sumtensor constructor follows."
57+
"A sumtensor `T` can only be declared as a sum of same-shaped tensors T1, T2,...,TN. The summand tensors are stored internally, which define the \"parts\" of the `sumtensor`. The parts of a `sumtensor` can be (dense) tensors (`tensor`), sparse tensors (` sptensor`), Kruskal tensors (`ktensor`), or Tucker tensors (`ttensor`). An example of the use of the sumtensor constructor follows."
5858
]
5959
},
6060
{

docs/source/tutorial/class_tenmat.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"cell_type": "markdown",
1717
"metadata": {},
1818
"source": [
19-
"We show how to convert a `tensor` to a 2D numpy array stored with extra information so that it can be converted back to a `tensor`. Converting to a 2D numpy array requies an ordered mapping of the `tensor` indices to the rows and the columns of the 2D numpy array."
19+
"We show how to convert a `tensor` to a 2D numpy array stored with extra information so that it can be converted back to a `tensor`. Converting to a 2D numpy array requires an ordered mapping of the `tensor` indices to the rows and the columns of the 2D numpy array."
2020
]
2121
},
2222
{

docs/source/tutorial/class_tensor.ipynb

+2-2
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
"metadata": {},
108108
"source": [
109109
"## Specifying trailing singleton dimensions in a `tensor`\n",
110-
"Likewise, trailing singleton dimensions must be explictly specified."
110+
"Likewise, trailing singleton dimensions must be explicitly specified."
111111
]
112112
},
113113
{
@@ -136,7 +136,7 @@
136136
"cell_type": "markdown",
137137
"metadata": {},
138138
"source": [
139-
"## The constitutent parts of a `tensor`"
139+
"## The constituent parts of a `tensor`"
140140
]
141141
},
142142
{

docs/source/tutorial/class_ttensor.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@
630630
"metadata": {},
631631
"source": [
632632
"### Compare visualizations\n",
633-
"We can compare the results of reconstruction. There is no degredation in doing only a partial reconstruction. Downsampling is obviously lower resolution, but the same result as first doing the full reconstruction and then downsampling."
633+
"We can compare the results of reconstruction. There is no degradation in doing only a partial reconstruction. Downsampling is obviously lower resolution, but the same result as first doing the full reconstruction and then downsampling."
634634
]
635635
},
636636
{

profiling/algorithms_profiling.ipynb

+4-4
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
" label:\n",
9191
" The user-supplied label to distinguish a test run.\n",
9292
" params:\n",
93-
" Paramters passed to the algorithm function.\n",
93+
" Parameters passed to the algorithm function.\n",
9494
" 'rank' may be given to the CP algorithms; 'tol' and 'verbosity' to hosvd.\n",
9595
" \"\"\"\n",
9696
"\n",
@@ -108,7 +108,7 @@
108108
" # stop collecting data, and send data to Stats object and sort\n",
109109
" profiler.disable()\n",
110110
"\n",
111-
" # save profiling ouput to sub-directory specific to the function being tested.\n",
111+
" # save profiling output to sub-directory specific to the function being tested.\n",
112112
" output_directory = f\"./pstats_files/{algorithm_name}\"\n",
113113
" if not os.path.exists(output_directory):\n",
114114
" os.makedirs(output_directory) # create directory if it doesn't exist\n",
@@ -155,7 +155,7 @@
155155
" label:\n",
156156
" The user-supplied label to distinguish a test run. This will be used in the output file name.\n",
157157
" params:\n",
158-
" Paramters passed to the algorithm function.\n",
158+
" Parameters passed to the algorithm function.\n",
159159
" 'rank' may be given to the CP algorithms; 'tol' and 'verbosity' to hosvd.\n",
160160
" \"\"\"\n",
161161
"\n",
@@ -410,7 +410,7 @@
410410
"source": [
411411
"### Generating all algorithms' profiling images\n",
412412
" \n",
413-
"The cell bellow will generate all profiling images for all algorithms in `./gprof2dot_images/<specific_algorithm>`"
413+
"The cell below will generate all profiling images for all algorithms in `./gprof2dot_images/<specific_algorithm>`"
414414
]
415415
},
416416
{

pyproject.toml

+20
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ dev = [
4040
# Also in pre-commit
4141
"ruff>=0.7,<0.8",
4242
"pre-commit>=4.0,<5.0",
43+
"codespell>=2.3.0,<2.4.0"
4344
]
4445
doc = [
4546
"sphinx >= 4.0",
@@ -120,3 +121,22 @@ addopts = "--doctest-modules pyttb"
120121
filterwarnings = [
121122
"ignore:.*deprecated.*:"
122123
]
124+
125+
[tool.codespell]
126+
skip = [
127+
# Built documentation
128+
"./docs/build",
129+
"./docs/jupyter_execute",
130+
# Project build artifacts
131+
"./build"
132+
]
133+
count = true
134+
ignore-words-list = [
135+
# Conventions carried from MATLAB ttb (consider changing)
136+
"ans",
137+
"siz",
138+
# Tensor/repo Nomenclature
139+
"COO",
140+
"nd",
141+
"als",
142+
]

pyttb/cp_als.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def cp_als( # noqa: PLR0912,PLR0913,PLR0915
7676
7777
Example
7878
-------
79-
Random initialization causes slight pertubation in intermediate results.
79+
Random initialization causes slight perturbation in intermediate results.
8080
`...` is our place holder for these numeric values.
8181
Example using default values ("random" initialization):
8282

pyttb/cp_apr.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def cp_apr( # noqa: PLR0913
104104
assert init.ndims == N, "Initial guess does not have the right number of modes"
105105
assert (
106106
init.ncomponents == rank
107-
), "Initial guess does not have the right number of componenets"
107+
), "Initial guess does not have the right number of components"
108108
for n in range(N):
109109
if init.shape[n] != input_tensor.shape[n]:
110110
assert False, f"Mode {n} of the initial guess is the wrong size"
@@ -256,7 +256,7 @@ def tt_cp_apr_mu( # noqa: PLR0912,PLR0913,PLR0915
256256
M.normalize(normtype=1)
257257
Phi = [] # np.zeros((N,))#cell(N,1)
258258
for n in range(N):
259-
# TODO prepopulation Phi instead of appen should be faster
259+
# TODO prepopulation Phi instead of append should be faster
260260
Phi.append(np.zeros(M.factor_matrices[n].shape))
261261
kktModeViolations = np.zeros((N,))
262262

@@ -488,7 +488,7 @@ def tt_cp_apr_pdnr( # noqa: PLR0912,PLR0913,PLR0915
488488

489489
if isinstance(input_tensor, ttb.sptensor) and isSparse and precompinds:
490490
# Precompute sparse index sets for all the row subproblems.
491-
# Takes more memory but can cut exectuion time significantly in some cases.
491+
# Takes more memory but can cut execution time significantly in some cases.
492492
if printitn > 0:
493493
print("\tPrecomuting sparse index sets...")
494494
sparseIx = []
@@ -847,7 +847,7 @@ def tt_cp_apr_pqnr( # noqa: PLR0912,PLR0913,PLR0915
847847

848848
if isinstance(input_tensor, ttb.sptensor) and precompinds:
849849
# Precompute sparse index sets for all the row subproblems.
850-
# Takes more memory but can cut exectuion time significantly in some cases.
850+
# Takes more memory but can cut execution time significantly in some cases.
851851
if printitn > 0:
852852
print("\tPrecomuting sparse index sets...")
853853
sparseIx = []
@@ -989,12 +989,12 @@ def tt_cp_apr_pqnr( # noqa: PLR0912,PLR0913,PLR0915
989989
delg[:, lbfgsPos] = tmp_delg
990990
rho[lbfgsPos] = tmp_rho
991991
else:
992-
# Rho is required to be postive; if not, then skip the L-BFGS
992+
# Rho is required to be positive; if not, then skip the L-BFGS
993993
# update pair. The recommended safeguard for full BFGS is
994994
# Powell damping, but not clear how to damp in 2-loop L-BFGS
995995
if dispLineWarn:
996996
warnings.warn(
997-
"WARNING: skipping L-BFGS update, rho whould be "
997+
"WARNING: skipping L-BFGS update, rho would be "
998998
f"1 / {tmp_delm * tmp_delg}"
999999
)
10001000
# Roll back lbfgsPos since it will increment later.
@@ -1384,7 +1384,7 @@ def tt_linesearch_prowsubprob( # noqa: PLR0913
13841384
max_steps:
13851385
maximum number of steps to try (suggest 10)
13861386
suff_decr:
1387-
sufficent decrease for convergence (suggest 1.0e-4)
1387+
sufficient decrease for convergence (suggest 1.0e-4)
13881388
isSparse:
13891389
sparsity flag for computing the objective
13901390
data_row:
@@ -1414,7 +1414,7 @@ def tt_linesearch_prowsubprob( # noqa: PLR0913
14141414

14151415
stepSize = step_len
14161416

1417-
# Evalute the current objective value
1417+
# Evaluate the current objective value
14181418
f_old = -tt_loglikelihood_row(isSparse, data_row, model_old, Pi)
14191419
num_evals = 1
14201420
count = 1
@@ -1613,7 +1613,7 @@ def get_search_dir_pqnr( # noqa: PLR0913
16131613
lbfgsSize = delta_model.shape[1]
16141614

16151615
# Determine active and free variables.
1616-
# TODO: is the bellow relevant?
1616+
# TODO: is the below relevant?
16171617
# If epsActSet is zero, then the following works:
16181618
# fixedVars = find((m_row == 0) & (grad' > 0));
16191619
# For the general case this works but is less clear and assumes m_row > 0:
@@ -1747,7 +1747,7 @@ def calculate_phi( # noqa: PLR0913
17471747
Pi: np.ndarray,
17481748
epsilon: float,
17491749
) -> np.ndarray:
1750-
"""Calcualte Phi.
1750+
"""Calculate Phi.
17511751
17521752
Parameters
17531753
----------

pyttb/gcp/optimizers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ def lbfgsb_func_grad(vector: np.ndarray):
512512

513513
lbfgsb_info["final_f"] = final_f
514514
lbfgsb_info["callback"] = vars(monitor)
515-
# Unregister monitor in case of re-use
515+
# Unregister monitor in case of reuse
516516
self._solver_kwargs["callback"] = monitor.callback
517517

518518
# TODO big print output

pyttb/hosvd.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def hosvd( # noqa: PLR0912,PLR0913,PLR0915
116116
ranks[k] = np.where(eigsum > eigsumthresh)[0][-1]
117117

118118
if verbosity > 5:
119-
print("Reverse cummulative sum of evals of Gram matrix:")
119+
print("Reverse cumulative sum of evals of Gram matrix:")
120120
for i, a_sum in enumerate(eigsum):
121121
print_msg = f"{i: d}: {a_sum: 6.4f}"
122122
if i == ranks[k]:

pyttb/ktensor.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ def to_tenmat(
945945
Mapping of column indices.
946946
cdims_cyclic:
947947
When only rdims is specified maps a single rdim to the rows and
948-
the remaining dimensons span the columns. _fc_ (forward cyclic)
948+
the remaining dimensions span the columns. _fc_ (forward cyclic)
949949
in the order range(rdims,self.ndims()) followed by range(0, rdims).
950950
_bc_ (backward cyclic) range(rdims-1, -1, -1) then
951951
range(self.ndims(), rdims, -1).
@@ -1378,7 +1378,7 @@ def normalize(
13781378

13791379
if sort:
13801380
if self.ncomponents > 1:
1381-
# indices of srting in descending order
1381+
# indices of string in descending order
13821382
p = np.argsort(self.weights)[::-1]
13831383
self.arrange(permutation=p)
13841384

@@ -2300,7 +2300,7 @@ def viz( # noqa: PLR0912, PLR0913
23002300
>>> fig, axs = K.viz(show_figure=False) # doctest: +ELLIPSIS
23012301
>>> plt.close(fig)
23022302
2303-
Define a more realistic plot fuctions with x labels,
2303+
Define a more realistic plot functions with x labels,
23042304
control relative widths of each plot,
23052305
and set mode titles.
23062306

0 commit comments

Comments
 (0)