ndplex 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ndplex-0.1.0/.gitignore +6 -0
- ndplex-0.1.0/ATTRIBUTION.md +58 -0
- ndplex-0.1.0/CHANGELOG.md +21 -0
- ndplex-0.1.0/CITATION.cff +42 -0
- ndplex-0.1.0/LICENSE +21 -0
- ndplex-0.1.0/PKG-INFO +196 -0
- ndplex-0.1.0/README.md +167 -0
- ndplex-0.1.0/docs/phase1_audit.md +231 -0
- ndplex-0.1.0/docs/phase2_package.md +195 -0
- ndplex-0.1.0/docs/phase3_ci.md +129 -0
- ndplex-0.1.0/docs/phase4_release.md +111 -0
- ndplex-0.1.0/pyproject.toml +70 -0
- ndplex-0.1.0/src/ndplex/__init__.py +42 -0
- ndplex-0.1.0/src/ndplex/_core.py +399 -0
- ndplex-0.1.0/src/ndplex/_oeis.py +120 -0
- ndplex-0.1.0/tests/_impl.py +32 -0
- ndplex-0.1.0/tests/conftest.py +26 -0
- ndplex-0.1.0/tests/differential_check.py +124 -0
- ndplex-0.1.0/tests/mutation_check.py +283 -0
- ndplex-0.1.0/tests/mutation_equivalent.txt +30 -0
- ndplex-0.1.0/tests/ndplex_original.py +524 -0
- ndplex-0.1.0/tests/primes.py +22 -0
- ndplex-0.1.0/tests/test_3d_4d.py +309 -0
- ndplex-0.1.0/tests/test_edges_func_arglocs.py +279 -0
- ndplex-0.1.0/tests/test_known_issues.py +445 -0
- ndplex-0.1.0/tests/test_oeis.py +214 -0
- ndplex-0.1.0/tests/test_original_copy.py +21 -0
- ndplex-0.1.0/tests/test_package.py +63 -0
- ndplex-0.1.0/tests/test_pascal_2d.py +148 -0
- ndplex-0.1.0/tests/test_platform.py +182 -0
- ndplex-0.1.0/tests/test_readme.py +41 -0
- ndplex-0.1.0/tests/test_sequences.py +230 -0
ndplex-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
## Attribution & References
|
|
2
|
+
|
|
3
|
+
### Provenance
|
|
4
|
+
|
|
5
|
+
This repository contains work of three kinds. They are kept apart so that credit, and responsibility for errors, lands in the right place.
|
|
6
|
+
|
|
7
|
+
**A. Original work: Ted Teske (2019–2024), sole author**
|
|
8
|
+
|
|
9
|
+
- The n-Dimensional m-Plex ("ndplex") array: a generic Pascal's array of any dimension, as an `np.ndarray` subclass with user-defined edges, node-generating function (`func`) and argument locations (`arg_locs`, including the `None`-means-on-the-edge convention).
|
|
10
|
+
- `diag`, the general line or cross-section through the array (loc, one or more moves, optional sums), and `as_tri`, the array as a triangle, tetrahedron or n-simplex.
|
|
11
|
+
- `oeis` (row-by-row OEIS lookup), `diag_as_hist` (weighted histograms with a normal overlay) and `plot_ndplex` (the array or triangle with highlighted diagonals).
|
|
12
|
+
- All of `ndplex_array.ipynb`: the examples and the observations in them, including the simplex/duplex/triplex triangles, the binomial-to-normal histograms, Fibonacci and Narayana's cows from steep diagonals, the slope table, the moving-cost and rental-rate model, and the explorations with primes.
|
|
13
|
+
|
|
14
|
+
**B. Collaborative work: Ted Teske with Claude (Anthropic), 2026**
|
|
15
|
+
|
|
16
|
+
- *Phase 1 audit* (`docs/phase1_audit.md`): running the notebook against current libraries; the findings on import side effects, the ndarray subclass, integer overflow (where it starts, why residues modulo powers of 2 survive it, and that part of the Fibonacci-mod-7 heatmap is overflow), arg_locs that wrap around the array, diag trimming genuine zeros, and oeis hiding network errors; the proposed 0.1.0 API.
|
|
17
|
+
- *Phase 1 regression suite* (`tests/`): the notebook's printed results pinned as tests, the property checks (binomial, multinomial, Lucas's theorem, digital roots), the known-issue tests, the offline OEIS stub and primes sieve, and the mutation check (`tests/mutation_check.py`).
|
|
18
|
+
- *Phase 2 package* (`src/ndplex`, `pyproject.toml`, `docs/phase2_package.md`): the package layout and lazy loading of `oeis`; the fixes for the Phase 1 findings (no import side effects, a single overflow warning naming the first overflowed node, exact `dtype=object` sums, derived arrays that keep working and pickle, zero padding for `arg_locs` outside the array, `diag` ending by geometry rather than at the first trailing zeros, argument checks, and `oeis` over https with failures reported and a `quiet` mode). The class's design, its node-generation loop, the edge-filling rotation, the `diag` move arithmetic and `as_tri` as a series of cross-sections (with its 2-D and 3-D moves) are Ted's, kept from the notebook (tier A). The `as_tri` moves for 4-D and up were changed in review so that layers are left-justified in every dimension (Ted's choice between the two layouts; the finding and the new move rule were made with Claude).
|
|
19
|
+
- *Phase 2 tests*: the suite moved to the package, the known-issue tests rewritten to the fixed behaviour, the new package, overflow, pickling and `oeis` tests, the differential check against the notebook code, and the mutation check adapted to the package.
|
|
20
|
+
- *Phase 3 tests and CI* (`.github/workflows/tests.yml`, `tests/test_platform.py`, `docs/phase3_ci.md`): the CI matrix (adapted from Ted's bounded-lognorm), the finding that overflow in narrow integer dtypes went unreported on NumPy < 2 and its fix (C12), and the platform tests.
|
|
21
|
+
- *Phase 4 packaging and release* (`.github/workflows/publish.yml`, `README.md`, `CITATION.cff`, `tests/test_readme.py`, `docs/phase4_release.md`): the publish workflow (adapted from Ted's bounded-lognorm), the README rewritten as the package's documentation with its examples run as tests, the citation metadata, and the release procedure. The choice of Green (2015) as a general source, the Zenodo and CITATION decisions, and the release itself are Ted's.
|
|
22
|
+
|
|
23
|
+
**C. Third-party work, cited below**
|
|
24
|
+
|
|
25
|
+
Attribution suggestion, not a rule: the usual convention in published work is that an AI system is not listed as an author, since authorship carries accountability an AI cannot hold. The conventional form is to claim the work as your own and acknowledge AI assistance, e.g. *"The test suite and audit were developed with assistance from Claude (Anthropic)."*
|
|
26
|
+
|
|
27
|
+
### References
|
|
28
|
+
|
|
29
|
+
**General source.** Ted cites Thomas M. Green's *The Simplex, Duplex and Pascal's Triangles* (2015; reference 10 below) as a general source for ndplex. The book covers Pascal's triangle and its relatives, simplexes, duplexes and higher-dimensional extensions, and recurrent sequences such as Fibonacci.
|
|
30
|
+
|
|
31
|
+
**Code adapted in the notebook's library cell (not in the package)**
|
|
32
|
+
|
|
33
|
+
1. `trim_trailing_zeros` (inside `diag`) is adapted from an answer to "Trim trailing zeros of a numpy array along each axis", Stack Overflow question 55917328. https://stackoverflow.com/questions/55917328
|
|
34
|
+
2. The query inside `oeis` is adapted from Andrew Walker's `oeis` package. https://github.com/AndrewWalker/oeis — its `setup.py` declares a BSD license; the repository has no LICENSE file (checked November 2026).
|
|
35
|
+
|
|
36
|
+
*Both are kept here as history. The package does not contain either (decision D9): `diag` now ends where its moves leave the array (`_trim_outside` in `src/ndplex/_core.py`, written from scratch for the change in behaviour) and `oeis`'s request is written from scratch with the standard library. The notebook (`ndplex_array.ipynb`) still contains the originals.*
|
|
37
|
+
|
|
38
|
+
**Code and data used only in the notebook's examples**
|
|
39
|
+
|
|
40
|
+
3. `sum_digits`, from Andreas K.'s answer to Stack Overflow question 48817036. https://stackoverflow.com/questions/48817036
|
|
41
|
+
4. `primesfrom2to`, from an answer to Stack Overflow question 2068372. https://stackoverflow.com/questions/2068372
|
|
42
|
+
5. The first 1000 primes, downloaded from a GitHub gist by cblanc. https://gist.github.com/cblanc/46ebbba6f42f61e60666
|
|
43
|
+
|
|
44
|
+
**Mathematics and sources cited in the notebook**
|
|
45
|
+
|
|
46
|
+
6. The On-Line Encyclopedia of Integer Sequences (OEIS). https://oeis.org — the source of the sequence names `oeis()` prints; its text output format is described at https://oeis.org/eishelp1.html.
|
|
47
|
+
7. Pascal's triangle and the bell curve. AMS Feature Column. http://www.ams.org/publicoutreach/feature-column/fcarc-normal
|
|
48
|
+
8. Pascal's triangle modulo n (Sierpinski's gasket). http://orion.math.iastate.edu/reu/oldREU/modupasc.htm
|
|
49
|
+
9. Hypercube; Simplex. Wikipedia. https://en.wikipedia.org/wiki/Hypercube, https://en.wikipedia.org/wiki/Simplex
|
|
50
|
+
10. Green, Thomas M. *The Simplex, Duplex and Pascal's Triangles: Relatives of Pascal's Triangle, with Excursions Into Hyperspace*. CreateSpace Independent Publishing Platform, 2015. 176 pp. ISBN 9781514677094. https://books.google.com/books/about/The_Simplex_Duplex_and_Pascal_s_Triangle.html?id=P0cDswEACAAJ (also cited in the notebook, via https://www.amazon.com/Simplex-Duplex-Pascals-Triangles-Excursions/dp/1514677091). **A general source for the project** (see the note above), not only for the notebook section that cites it.
|
|
51
|
+
11. Narayana's cows sequence, OEIS A000930 (https://oeis.org/A000930), and the paper linked from the notebook (JIM 96 proceedings). http://jim.afim-asso.org/jim96/actes/Allouche.ps
|
|
52
|
+
|
|
53
|
+
**Used in the Phase 1 tests**
|
|
54
|
+
|
|
55
|
+
12. Lucas's theorem (a binomial coefficient modulo a prime, from base-p digits); for p = 2 it gives: C(i + j, i) is odd exactly when i AND j = 0. https://en.wikipedia.org/wiki/Lucas%27s_theorem
|
|
56
|
+
13. The multinomial theorem: the nodes of layer r of the d-dimensional default ndplex sum to d^r.
|
|
57
|
+
|
|
58
|
+
*Links in the notebook have not yet been checked; a link audit is planned with the examples notebook (Phase 5).*
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The project follows [Semantic Versioning](https://semver.org/); while the version is 0.x, minor releases may change the API.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 (2026-11-06)
|
|
6
|
+
|
|
7
|
+
First release, and the first version as a package. Before this, ndplex was the first code cell of `ndplex_array.ipynb` (Ted Teske, 2019–2024). The notebook's results are kept except where a change is listed below; each change is documented, with migration notes, in `docs/phase2_package.md`, `docs/phase3_ci.md` and `docs/phase4_release.md`.
|
|
8
|
+
|
|
9
|
+
- **Package layout.** `src/ndplex`: the `ndplex` class (`_core.py`) and `oeis` (`_oeis.py`). `from ndplex import ndplex, oeis` works as before. `import ndplex` needs only NumPy (≥ 1.23.5); `oeis` uses the standard library and is loaded on first use.
|
|
10
|
+
- **Plotting is left out.** `plot_ndplex` and `diag_as_hist` are not in the package; importing them raises an `ImportError` that points to the notebook in the repository, which has the original versions (Phase 4, C13; an examples notebook with working copies is planned).
|
|
11
|
+
- **No import side effects.** Importing no longer silences warnings or restyles matplotlib.
|
|
12
|
+
- **Overflow is reported.** If any node overflows the dtype, construction issues one `RuntimeWarning` naming the first node that did. Values are unchanged. `dtype=object` is exact, now including sums in `diag` and `as_tri` past 2^63.
|
|
13
|
+
- **Overflow is reported for every integer dtype, on every NumPy version** (Phase 3, `docs/phase3_ci.md`, C12). On NumPy < 2, overflow in int8, int16, int32 and unsigned arrays went unreported. An integer from `func` that does not fit the dtype is now wrapped and reported, where it used to wrap silently (NumPy < 2) or raise `OverflowError` (NumPy 2, or a Python int beyond int64).
|
|
14
|
+
- **CI.** Tests run on Linux (Python 3.10–3.15), macOS and Windows, on NumPy 1.23.5 and the latest NumPy.
|
|
15
|
+
- **Derived arrays keep working.** `diag` works on slices, arithmetic results, copies and unpickled arrays. Reductions (`sum`, `max`, ...) return plain scalars. Pickling keeps `edges`, `func` and `arg_locs` (a `func` that cannot be pickled comes back as `None`).
|
|
16
|
+
- **`arg_locs` outside the array read 0** instead of wrapping around to the far side. Positive offsets raise `ValueError`. The default is `arg_locs=None`.
|
|
17
|
+
- **`diag` ends where the moves leave the array**, so genuine trailing zeros are kept and all-zero lines return zeros instead of raising `IndexError`.
|
|
18
|
+
- **`as_tri` layers are left-justified in every dimension.** 2-D and 3-D are unchanged; from 4-D up the notebook's layers were sheared. Values and sums are unchanged.
|
|
19
|
+
- **Arguments.** NumPy integer `edges` accepted; bad arguments raise `ValueError` with a message; the default dtype is `np.int64` on every platform; the default `func` is the builtin `sum`.
|
|
20
|
+
- **`oeis`.** https and a timeout; requests name ndplex in their User-Agent header, because oeis.org now refuses Python's default one (C14); network or format failures print `lookup failed (...)` instead of `no match`; `quiet=True` returns the results instead of printing.
|
|
21
|
+
- **Release.** Published to PyPI with Trusted Publishing (`.github/workflows/publish.yml`). The README is now the package's own documentation, and its examples run as tests. `CITATION.cff` added.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it using the metadata from this file."
|
|
3
|
+
type: software
|
|
4
|
+
title: "ndplex: the n-Dimensional m-Plex array, a generic Pascal's array for NumPy"
|
|
5
|
+
abstract: >-
|
|
6
|
+
A generic Pascal's array of any dimension, as a NumPy array subclass: by
|
|
7
|
+
default Pascal's rectangle, cube or hypercube, with user-defined edges,
|
|
8
|
+
node-generating function and argument locations. Includes lines and
|
|
9
|
+
cross-sections through the array (diag), the array as a triangle,
|
|
10
|
+
tetrahedron or n-simplex (as_tri), and row-by-row lookup in the On-Line
|
|
11
|
+
Encyclopedia of Integer Sequences (oeis).
|
|
12
|
+
authors:
|
|
13
|
+
- family-names: Teske
|
|
14
|
+
given-names: Ted
|
|
15
|
+
version: 0.1.0
|
|
16
|
+
license: MIT
|
|
17
|
+
# The Zenodo concept DOI and the version DOIs are added after the first
|
|
18
|
+
# Zenodo-archived release (0.1.0).
|
|
19
|
+
repository-code: "https://github.com/tedteske/ndplex"
|
|
20
|
+
url: "https://pypi.org/project/ndplex/"
|
|
21
|
+
keywords:
|
|
22
|
+
- Pascal's triangle
|
|
23
|
+
- Pascal's array
|
|
24
|
+
- combinatorics
|
|
25
|
+
- binomial coefficients
|
|
26
|
+
- multinomial coefficients
|
|
27
|
+
- simplex
|
|
28
|
+
- integer sequences
|
|
29
|
+
- OEIS
|
|
30
|
+
- NumPy
|
|
31
|
+
references:
|
|
32
|
+
- type: book
|
|
33
|
+
title: "The Simplex, Duplex and Pascal's Triangles: Relatives of Pascal's Triangle, with Excursions Into Hyperspace"
|
|
34
|
+
authors:
|
|
35
|
+
- family-names: Green
|
|
36
|
+
given-names: Thomas M.
|
|
37
|
+
year: 2015
|
|
38
|
+
publisher:
|
|
39
|
+
name: CreateSpace Independent Publishing Platform
|
|
40
|
+
isbn: "9781514677094"
|
|
41
|
+
pages: 176
|
|
42
|
+
notes: "A general source for ndplex."
|
ndplex-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Ted Teske
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ndplex-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ndplex
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The n-Dimensional m-Plex array: a generic Pascal's array (rectangle, cube or higher) with user-defined edges and node-generating function.
|
|
5
|
+
Project-URL: Homepage, https://github.com/tedteske/ndplex
|
|
6
|
+
Project-URL: Source, https://github.com/tedteske/ndplex
|
|
7
|
+
Project-URL: Issues, https://github.com/tedteske/ndplex/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/tedteske/ndplex/blob/master/CHANGELOG.md
|
|
9
|
+
Author: Ted Teske
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: binomial,combinatorics,integer sequences,multinomial,numpy,oeis,pascal's array,pascal's triangle,simplex
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Requires-Dist: numpy>=1.23.5
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# ndplex
|
|
31
|
+
|
|
32
|
+
**The n-Dimensional m-Plex array: a generic Pascal's array for NumPy.**
|
|
33
|
+
|
|
34
|
+
`ndplex` builds Pascal's rectangle, cube or hypercube as a NumPy array, and lets you change everything that defines it: the values on its edges, the rule that generates each interior node, and which neighbours that rule reads. It can then cut lines and cross-sections through the array, show the array as a triangle, tetrahedron or n-simplex, and look its rows up in the [On-Line Encyclopedia of Integer Sequences](https://oeis.org).
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
pip install ndplex
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
In Google Colab, run `!pip install ndplex` in a cell. ndplex needs Python 3.10 or later and NumPy 1.23.5 or later, nothing else. `oeis` needs a network connection when it is called.
|
|
43
|
+
|
|
44
|
+
## Quick start
|
|
45
|
+
|
|
46
|
+
By default, `ndplex(n)` is Pascal's rectangle: ones on the top and left edges, and every other node the sum of the node above it and the node to its left.
|
|
47
|
+
|
|
48
|
+
```pycon
|
|
49
|
+
>>> from ndplex import ndplex
|
|
50
|
+
>>> p = ndplex(6)
|
|
51
|
+
>>> print(p)
|
|
52
|
+
[[ 1 1 1 1 1 1]
|
|
53
|
+
[ 1 2 3 4 5 6]
|
|
54
|
+
[ 1 3 6 10 15 21]
|
|
55
|
+
[ 1 4 10 20 35 56]
|
|
56
|
+
[ 1 5 15 35 70 126]
|
|
57
|
+
[ 1 6 21 56 126 252]]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`as_tri` shows the same array as Pascal's triangle, justified left, or returns the sum of each row.
|
|
61
|
+
|
|
62
|
+
```pycon
|
|
63
|
+
>>> print(p.as_tri())
|
|
64
|
+
[[ 1 0 0 0 0 0]
|
|
65
|
+
[ 1 1 0 0 0 0]
|
|
66
|
+
[ 1 2 1 0 0 0]
|
|
67
|
+
[ 1 3 3 1 0 0]
|
|
68
|
+
[ 1 4 6 4 1 0]
|
|
69
|
+
[ 1 5 10 10 5 1]]
|
|
70
|
+
>>> print(p.as_tri(sums=True))
|
|
71
|
+
[ 1 2 4 8 16 32]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`diag` walks through the array from a starting node by a fixed step. Row 4 of the triangle is an anti-diagonal of the rectangle; the main diagonal holds the central binomial coefficients.
|
|
75
|
+
|
|
76
|
+
```pycon
|
|
77
|
+
>>> print(p.diag(loc=(4, 0), move=(-1, 1)))
|
|
78
|
+
[1 4 6 4 1]
|
|
79
|
+
>>> print(p.diag())
|
|
80
|
+
[ 1 2 6 20 70 252]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The steeper diagonals sum to the Fibonacci numbers:
|
|
84
|
+
|
|
85
|
+
```pycon
|
|
86
|
+
>>> f = ndplex(10)
|
|
87
|
+
>>> print([int(f.diag(loc=(k, 0), move=(-2, 1)).sum()) for k in range(10)])
|
|
88
|
+
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Other arrays
|
|
92
|
+
|
|
93
|
+
`ndplex(nrows, edges=(1, 1), arg_locs=None, func=sum, dtype=np.int64)`
|
|
94
|
+
|
|
95
|
+
- **`edges`** sets the front edges, as numbers or as sequences of length `nrows`. Their number sets the dimension. In 2-D, `edges[0]` fills column 0 and `edges[1]` fills row 0.
|
|
96
|
+
- **`func`** generates each interior node from a list of argument values. The default is `sum`.
|
|
97
|
+
- **`arg_locs`** gives where those arguments are, relative to the node. The default in 2-D is `[[-1, 0], [0, -1]]`, the nodes above and to the left. A `None` coordinate means "on the edge".
|
|
98
|
+
|
|
99
|
+
Odd numbers along the top edge give the squares, the square pyramidal numbers, and so on down the rows:
|
|
100
|
+
|
|
101
|
+
```pycon
|
|
102
|
+
>>> print(ndplex(5, edges=(1, [1, 3, 5, 7, 9])))
|
|
103
|
+
[[ 1 3 5 7 9]
|
|
104
|
+
[ 1 4 9 16 25]
|
|
105
|
+
[ 1 5 14 30 55]
|
|
106
|
+
[ 1 6 20 50 105]
|
|
107
|
+
[ 1 7 27 77 182]]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Pascal's rule modulo 2 gives the Sierpinski pattern:
|
|
111
|
+
|
|
112
|
+
```pycon
|
|
113
|
+
>>> print(ndplex(6, func=lambda x: sum(x) % 2))
|
|
114
|
+
[[1 1 1 1 1 1]
|
|
115
|
+
[1 0 1 0 1 0]
|
|
116
|
+
[1 1 0 0 1 1]
|
|
117
|
+
[1 0 0 0 1 0]
|
|
118
|
+
[1 1 1 1 0 0]
|
|
119
|
+
[1 0 1 0 0 0]]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Adding the diagonal neighbour as a third argument gives the Delannoy numbers:
|
|
123
|
+
|
|
124
|
+
```pycon
|
|
125
|
+
>>> print(ndplex(6, arg_locs=[[-1, 0], [0, -1], [-1, -1]]))
|
|
126
|
+
[[ 1 1 1 1 1 1]
|
|
127
|
+
[ 1 3 5 7 9 11]
|
|
128
|
+
[ 1 5 13 25 41 61]
|
|
129
|
+
[ 1 7 25 63 129 231]
|
|
130
|
+
[ 1 9 41 129 321 681]
|
|
131
|
+
[ 1 11 61 231 681 1683]]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Higher dimensions
|
|
135
|
+
|
|
136
|
+
Three edges make Pascal's cube; `as_tri` shows it as a tetrahedron, layer by layer. Each layer holds the trinomial coefficients, and the layers sum to powers of 3.
|
|
137
|
+
|
|
138
|
+
```pycon
|
|
139
|
+
>>> c = ndplex(4, edges=3)
|
|
140
|
+
>>> print(c.as_tri()[2])
|
|
141
|
+
[[1 2 1 0]
|
|
142
|
+
[2 2 0 0]
|
|
143
|
+
[1 0 0 0]
|
|
144
|
+
[0 0 0 0]]
|
|
145
|
+
>>> print(c.as_tri(sums=True))
|
|
146
|
+
[ 1 3 9 27]
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The same works in any number of dimensions: `ndplex(5, edges=4)` is a 4-D array, and its `as_tri` is a 4-simplex.
|
|
150
|
+
|
|
151
|
+
## Large values
|
|
152
|
+
|
|
153
|
+
Node values grow quickly. With the default `int64`, the 2-D array is exact for nodes with `i + j <= 66`. If any node overflows, construction issues one `RuntimeWarning` naming the first node that did. For exact integers of any size, use `dtype=object`:
|
|
154
|
+
|
|
155
|
+
```pycon
|
|
156
|
+
>>> print(ndplex(70, dtype=object)[69, 69])
|
|
157
|
+
23623985175715118288974865541854103729000
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
When only a residue is needed, reduce inside `func` instead, as in the Sierpinski example above.
|
|
161
|
+
|
|
162
|
+
## Looking rows up in OEIS
|
|
163
|
+
|
|
164
|
+
`oeis` searches oeis.org for each row of an array and prints the best match. It sends one request per row, so please search a few rows at a time.
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from ndplex import ndplex, oeis
|
|
168
|
+
|
|
169
|
+
oeis(ndplex(5))
|
|
170
|
+
oeis(ndplex(9).as_tri(), trim=True, size=5) # rows of the triangle, zeros trimmed
|
|
171
|
+
matches = oeis(ndplex(5), quiet=True) # a list of (A-number, name) or None
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The output has one line per row, for example `row 2: https://oeis.org/A000217 Triangular numbers: ...`. The names come from OEIS and can change. If oeis.org cannot be reached or refuses the request, the row's line says `lookup failed (...)`. Each request identifies itself to oeis.org as `ndplex/<version>`.
|
|
175
|
+
|
|
176
|
+
## Plotting
|
|
177
|
+
|
|
178
|
+
From 0.1.0, plotting is left to the user, so `import ndplex` needs only NumPy. The notebook's `plot_ndplex` and `diag_as_hist` are in [`ndplex_array.ipynb`](https://github.com/tedteske/ndplex/blob/master/ndplex_array.ipynb) in the repository; an examples notebook that installs from PyPI is planned.
|
|
179
|
+
|
|
180
|
+
## Changes from the notebook
|
|
181
|
+
|
|
182
|
+
ndplex began as the first code cell of `ndplex_array.ipynb` (2019–2024). The package keeps the notebook's results except where a change is documented. The changes are listed in the [changelog](https://github.com/tedteske/ndplex/blob/master/CHANGELOG.md), with migration notes in [`docs/`](https://github.com/tedteske/ndplex/tree/master/docs). In brief: no import side effects, plotting left out, overflow reported, `arg_locs` outside the array read 0, `diag` ends where its moves leave the array, and `as_tri` layers are justified left in every dimension.
|
|
183
|
+
|
|
184
|
+
## Background and credits
|
|
185
|
+
|
|
186
|
+
ndplex is the original work of Ted Teske (2019–2024). A general source for it is Thomas M. Green, *The Simplex, Duplex and Pascal's Triangles: Relatives of Pascal's Triangle, with Excursions Into Hyperspace* (CreateSpace, 2015; ISBN 9781514677094).
|
|
187
|
+
|
|
188
|
+
The packaging, tests and audit (2026) were developed with assistance from Claude (Anthropic). [`ATTRIBUTION.md`](https://github.com/tedteske/ndplex/blob/master/ATTRIBUTION.md) sets out which work is whose, and the references.
|
|
189
|
+
|
|
190
|
+
## Citing
|
|
191
|
+
|
|
192
|
+
Citation metadata are in [`CITATION.cff`](https://github.com/tedteske/ndplex/blob/master/CITATION.cff); GitHub's "Cite this repository" button reads it.
|
|
193
|
+
|
|
194
|
+
## License
|
|
195
|
+
|
|
196
|
+
MIT. Copyright (c) 2019 Ted Teske.
|
ndplex-0.1.0/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# ndplex
|
|
2
|
+
|
|
3
|
+
**The n-Dimensional m-Plex array: a generic Pascal's array for NumPy.**
|
|
4
|
+
|
|
5
|
+
`ndplex` builds Pascal's rectangle, cube or hypercube as a NumPy array, and lets you change everything that defines it: the values on its edges, the rule that generates each interior node, and which neighbours that rule reads. It can then cut lines and cross-sections through the array, show the array as a triangle, tetrahedron or n-simplex, and look its rows up in the [On-Line Encyclopedia of Integer Sequences](https://oeis.org).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
pip install ndplex
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
In Google Colab, run `!pip install ndplex` in a cell. ndplex needs Python 3.10 or later and NumPy 1.23.5 or later, nothing else. `oeis` needs a network connection when it is called.
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
By default, `ndplex(n)` is Pascal's rectangle: ones on the top and left edges, and every other node the sum of the node above it and the node to its left.
|
|
18
|
+
|
|
19
|
+
```pycon
|
|
20
|
+
>>> from ndplex import ndplex
|
|
21
|
+
>>> p = ndplex(6)
|
|
22
|
+
>>> print(p)
|
|
23
|
+
[[ 1 1 1 1 1 1]
|
|
24
|
+
[ 1 2 3 4 5 6]
|
|
25
|
+
[ 1 3 6 10 15 21]
|
|
26
|
+
[ 1 4 10 20 35 56]
|
|
27
|
+
[ 1 5 15 35 70 126]
|
|
28
|
+
[ 1 6 21 56 126 252]]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`as_tri` shows the same array as Pascal's triangle, justified left, or returns the sum of each row.
|
|
32
|
+
|
|
33
|
+
```pycon
|
|
34
|
+
>>> print(p.as_tri())
|
|
35
|
+
[[ 1 0 0 0 0 0]
|
|
36
|
+
[ 1 1 0 0 0 0]
|
|
37
|
+
[ 1 2 1 0 0 0]
|
|
38
|
+
[ 1 3 3 1 0 0]
|
|
39
|
+
[ 1 4 6 4 1 0]
|
|
40
|
+
[ 1 5 10 10 5 1]]
|
|
41
|
+
>>> print(p.as_tri(sums=True))
|
|
42
|
+
[ 1 2 4 8 16 32]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`diag` walks through the array from a starting node by a fixed step. Row 4 of the triangle is an anti-diagonal of the rectangle; the main diagonal holds the central binomial coefficients.
|
|
46
|
+
|
|
47
|
+
```pycon
|
|
48
|
+
>>> print(p.diag(loc=(4, 0), move=(-1, 1)))
|
|
49
|
+
[1 4 6 4 1]
|
|
50
|
+
>>> print(p.diag())
|
|
51
|
+
[ 1 2 6 20 70 252]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The steeper diagonals sum to the Fibonacci numbers:
|
|
55
|
+
|
|
56
|
+
```pycon
|
|
57
|
+
>>> f = ndplex(10)
|
|
58
|
+
>>> print([int(f.diag(loc=(k, 0), move=(-2, 1)).sum()) for k in range(10)])
|
|
59
|
+
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Other arrays
|
|
63
|
+
|
|
64
|
+
`ndplex(nrows, edges=(1, 1), arg_locs=None, func=sum, dtype=np.int64)`
|
|
65
|
+
|
|
66
|
+
- **`edges`** sets the front edges, as numbers or as sequences of length `nrows`. Their number sets the dimension. In 2-D, `edges[0]` fills column 0 and `edges[1]` fills row 0.
|
|
67
|
+
- **`func`** generates each interior node from a list of argument values. The default is `sum`.
|
|
68
|
+
- **`arg_locs`** gives where those arguments are, relative to the node. The default in 2-D is `[[-1, 0], [0, -1]]`, the nodes above and to the left. A `None` coordinate means "on the edge".
|
|
69
|
+
|
|
70
|
+
Odd numbers along the top edge give the squares, the square pyramidal numbers, and so on down the rows:
|
|
71
|
+
|
|
72
|
+
```pycon
|
|
73
|
+
>>> print(ndplex(5, edges=(1, [1, 3, 5, 7, 9])))
|
|
74
|
+
[[ 1 3 5 7 9]
|
|
75
|
+
[ 1 4 9 16 25]
|
|
76
|
+
[ 1 5 14 30 55]
|
|
77
|
+
[ 1 6 20 50 105]
|
|
78
|
+
[ 1 7 27 77 182]]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Pascal's rule modulo 2 gives the Sierpinski pattern:
|
|
82
|
+
|
|
83
|
+
```pycon
|
|
84
|
+
>>> print(ndplex(6, func=lambda x: sum(x) % 2))
|
|
85
|
+
[[1 1 1 1 1 1]
|
|
86
|
+
[1 0 1 0 1 0]
|
|
87
|
+
[1 1 0 0 1 1]
|
|
88
|
+
[1 0 0 0 1 0]
|
|
89
|
+
[1 1 1 1 0 0]
|
|
90
|
+
[1 0 1 0 0 0]]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Adding the diagonal neighbour as a third argument gives the Delannoy numbers:
|
|
94
|
+
|
|
95
|
+
```pycon
|
|
96
|
+
>>> print(ndplex(6, arg_locs=[[-1, 0], [0, -1], [-1, -1]]))
|
|
97
|
+
[[ 1 1 1 1 1 1]
|
|
98
|
+
[ 1 3 5 7 9 11]
|
|
99
|
+
[ 1 5 13 25 41 61]
|
|
100
|
+
[ 1 7 25 63 129 231]
|
|
101
|
+
[ 1 9 41 129 321 681]
|
|
102
|
+
[ 1 11 61 231 681 1683]]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Higher dimensions
|
|
106
|
+
|
|
107
|
+
Three edges make Pascal's cube; `as_tri` shows it as a tetrahedron, layer by layer. Each layer holds the trinomial coefficients, and the layers sum to powers of 3.
|
|
108
|
+
|
|
109
|
+
```pycon
|
|
110
|
+
>>> c = ndplex(4, edges=3)
|
|
111
|
+
>>> print(c.as_tri()[2])
|
|
112
|
+
[[1 2 1 0]
|
|
113
|
+
[2 2 0 0]
|
|
114
|
+
[1 0 0 0]
|
|
115
|
+
[0 0 0 0]]
|
|
116
|
+
>>> print(c.as_tri(sums=True))
|
|
117
|
+
[ 1 3 9 27]
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The same works in any number of dimensions: `ndplex(5, edges=4)` is a 4-D array, and its `as_tri` is a 4-simplex.
|
|
121
|
+
|
|
122
|
+
## Large values
|
|
123
|
+
|
|
124
|
+
Node values grow quickly. With the default `int64`, the 2-D array is exact for nodes with `i + j <= 66`. If any node overflows, construction issues one `RuntimeWarning` naming the first node that did. For exact integers of any size, use `dtype=object`:
|
|
125
|
+
|
|
126
|
+
```pycon
|
|
127
|
+
>>> print(ndplex(70, dtype=object)[69, 69])
|
|
128
|
+
23623985175715118288974865541854103729000
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
When only a residue is needed, reduce inside `func` instead, as in the Sierpinski example above.
|
|
132
|
+
|
|
133
|
+
## Looking rows up in OEIS
|
|
134
|
+
|
|
135
|
+
`oeis` searches oeis.org for each row of an array and prints the best match. It sends one request per row, so please search a few rows at a time.
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from ndplex import ndplex, oeis
|
|
139
|
+
|
|
140
|
+
oeis(ndplex(5))
|
|
141
|
+
oeis(ndplex(9).as_tri(), trim=True, size=5) # rows of the triangle, zeros trimmed
|
|
142
|
+
matches = oeis(ndplex(5), quiet=True) # a list of (A-number, name) or None
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The output has one line per row, for example `row 2: https://oeis.org/A000217 Triangular numbers: ...`. The names come from OEIS and can change. If oeis.org cannot be reached or refuses the request, the row's line says `lookup failed (...)`. Each request identifies itself to oeis.org as `ndplex/<version>`.
|
|
146
|
+
|
|
147
|
+
## Plotting
|
|
148
|
+
|
|
149
|
+
From 0.1.0, plotting is left to the user, so `import ndplex` needs only NumPy. The notebook's `plot_ndplex` and `diag_as_hist` are in [`ndplex_array.ipynb`](https://github.com/tedteske/ndplex/blob/master/ndplex_array.ipynb) in the repository; an examples notebook that installs from PyPI is planned.
|
|
150
|
+
|
|
151
|
+
## Changes from the notebook
|
|
152
|
+
|
|
153
|
+
ndplex began as the first code cell of `ndplex_array.ipynb` (2019–2024). The package keeps the notebook's results except where a change is documented. The changes are listed in the [changelog](https://github.com/tedteske/ndplex/blob/master/CHANGELOG.md), with migration notes in [`docs/`](https://github.com/tedteske/ndplex/tree/master/docs). In brief: no import side effects, plotting left out, overflow reported, `arg_locs` outside the array read 0, `diag` ends where its moves leave the array, and `as_tri` layers are justified left in every dimension.
|
|
154
|
+
|
|
155
|
+
## Background and credits
|
|
156
|
+
|
|
157
|
+
ndplex is the original work of Ted Teske (2019–2024). A general source for it is Thomas M. Green, *The Simplex, Duplex and Pascal's Triangles: Relatives of Pascal's Triangle, with Excursions Into Hyperspace* (CreateSpace, 2015; ISBN 9781514677094).
|
|
158
|
+
|
|
159
|
+
The packaging, tests and audit (2026) were developed with assistance from Claude (Anthropic). [`ATTRIBUTION.md`](https://github.com/tedteske/ndplex/blob/master/ATTRIBUTION.md) sets out which work is whose, and the references.
|
|
160
|
+
|
|
161
|
+
## Citing
|
|
162
|
+
|
|
163
|
+
Citation metadata are in [`CITATION.cff`](https://github.com/tedteske/ndplex/blob/master/CITATION.cff); GitHub's "Cite this repository" button reads it.
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
MIT. Copyright (c) 2019 Ted Teske.
|