pythonic-peano-arithmetic 0.3.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Yusuke Hayashi
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.
@@ -0,0 +1,240 @@
1
+ Metadata-Version: 2.4
2
+ Name: pythonic-peano-arithmetic
3
+ Version: 0.3.0
4
+ Summary: Build arithmetic from Peano axioms and trace algebraic real roots
5
+ Keywords: arithmetic,education,mathematics,peano
6
+ Author: Yusuke Hayashi
7
+ Author-email: Yusuke Hayashi <yusuke8h@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Education
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Education
19
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Project-URL: Documentation, https://peano.yusuke-hayashi.com/en/
23
+ Project-URL: Homepage, https://peano.yusuke-hayashi.com/en/
24
+ Project-URL: Issues, https://github.com/yhay81/pythonic-peano-arithmetic/issues
25
+ Project-URL: Repository, https://github.com/yhay81/pythonic-peano-arithmetic
26
+ Description-Content-Type: text/markdown
27
+
28
+ # Pythonic Peano Arithmetic
29
+
30
+ An educational Python library that constructs natural numbers, integers,
31
+ rational numbers, and polynomials from simple definitions, then uses rational
32
+ intervals to study algebraic real roots.
33
+
34
+ The implementation is intentionally small and explicit. Its purpose is to make
35
+ the correspondence between a mathematical definition and executable Python
36
+ visible—not to compete with Python's built-in numeric types.
37
+
38
+ The interactive course runs entirely in the browser with Zensical and Pyodide:
39
+
40
+ - [English course](https://peano.yusuke-hayashi.com/en/)
41
+ - [日本語の教材](https://peano.yusuke-hayashi.com/)
42
+
43
+ ## What you can observe
44
+
45
+ - natural numbers built from `0` and the successor operation;
46
+ - recursive definitions of addition and multiplication;
47
+ - integers as equivalence classes of pairs of natural numbers;
48
+ - rationals as equivalence classes of integer pairs;
49
+ - polynomials as finite coefficient sequences;
50
+ - Sturm sequences and bisection over rational isolating intervals;
51
+ - Python mechanisms that connect notation to implementation: special methods,
52
+ decorators, frozen dataclasses, coercion, and operator dispatch.
53
+
54
+ ## Install
55
+
56
+ Python 3.10 or later is required.
57
+
58
+ ```bash
59
+ pip install pythonic-peano-arithmetic
60
+ ```
61
+
62
+ For repository development, install
63
+ [uv](https://docs.astral.sh/uv/) and run:
64
+
65
+ ```bash
66
+ git clone https://github.com/yhay81/pythonic-peano-arithmetic.git
67
+ cd pythonic-peano-arithmetic
68
+ make install
69
+ make check
70
+ ```
71
+
72
+ ## A five-minute tour
73
+
74
+ ### Natural numbers: follow the recursive definition
75
+
76
+ ```python
77
+ from peano import natural_number
78
+ from peano.utils import config_log
79
+
80
+ config_log(log_level=4)
81
+ two = natural_number(2)
82
+ one = natural_number(1)
83
+ print(two + one)
84
+ ```
85
+
86
+ The trace names the rule used at each step:
87
+
88
+ ```text
89
+ [addition: base] add(S(S(0)), 0) -> S(S(0))
90
+ [addition: recursive] add(S(S(0)), S(0)) -> S(add(S(S(0)), 0))
91
+ 3
92
+ ```
93
+
94
+ These two lines correspond directly to:
95
+
96
+ ```text
97
+ n + 0 = n
98
+ n + S(m) = S(n + m)
99
+ ```
100
+
101
+ Pass `locale="ja"` to `config_log` to show Japanese rule labels.
102
+
103
+ ### Integers: equality of representatives
104
+
105
+ An integer is represented by a pair `(a, b)`, read as `a - b`. Different pairs
106
+ can represent the same integer:
107
+
108
+ ```python
109
+ from peano import integer
110
+
111
+ print(integer(3, 1) == integer(4, 2))
112
+ ```
113
+
114
+ The implementation checks the defining equivalence:
115
+
116
+ ```text
117
+ (a, b) ~ (c, d) exactly when a + d = b + c
118
+ ```
119
+
120
+ ### Rationals: equality by cross multiplication
121
+
122
+ ```python
123
+ from peano import rational
124
+
125
+ print(rational(1, 2) == rational(2, 4))
126
+ ```
127
+
128
+ This follows the definition `p/q ~ r/s` exactly when `p*s = q*r`.
129
+
130
+ ### Algebraic real roots: approach √2 with rational intervals
131
+
132
+ ```python
133
+ from peano import Polynomial, Q_ONE, Q_ZERO, algebraic_root, rational
134
+
135
+ x_squared_minus_two = Polynomial(rational(-2, 1), Q_ZERO, Q_ONE)
136
+ root = algebraic_root(x_squared_minus_two, (1, 1), (2, 1))
137
+
138
+ for interval in root.trace(5):
139
+ print(interval)
140
+ ```
141
+
142
+ Every endpoint remains rational. The intervals are nested, their widths halve,
143
+ and each interval still isolates the positive root of `x² - 2`.
144
+
145
+ ## Definition-to-implementation map
146
+
147
+ | Mathematical idea | Python implementation |
148
+ | --- | --- |
149
+ | zero and successor `S(n)` | `NaturalNumber`, `successor` |
150
+ | `0` differs from every successor | `NaturalNumber.__eq__` |
151
+ | successor is injective | `NaturalNumber.__eq__` |
152
+ | `n + 0 = n`, `n + S(m) = S(n + m)` | `NaturalNumber.__add__` |
153
+ | `n × 0 = 0`, `n × S(m) = n + n × m` | `NaturalNumber.__mul__` |
154
+ | `(a,b) ~ (c,d) ↔ a+d=b+c` | `Integer.__eq__` |
155
+ | `p/q ~ r/s ↔ ps=qr` | `Rational.__eq__` |
156
+ | coefficient sequence `(a₀,a₁,...)` | `Polynomial` |
157
+ | distinct roots in an interval | `sturm_sequence`, `count_real_roots` |
158
+ | one algebraic root | `AlgebraicRoot`, `RationalInterval` |
159
+
160
+ Mathematical induction is a proof principle, not a test performed by Python.
161
+ The finite tests check representative laws and guard the intended mapping
162
+ between the definitions and code.
163
+
164
+ ## Logging
165
+
166
+ Operations return ordinary values. Internally, selected methods return a value
167
+ and a lazily constructed explanation; the `@log` decorator exposes only the
168
+ value and emits the explanation when logging is enabled.
169
+
170
+ ```python
171
+ from peano.utils import config_log
172
+
173
+ config_log(
174
+ log_level=4,
175
+ max_lines=200,
176
+ # fmt="Level %(levelno)s: %(message)s", # expose internal levels if needed
177
+ )
178
+ ```
179
+
180
+ Lower log levels reveal more detail. The numeric levels are an internal filter,
181
+ so the default display emphasizes rule names instead.
182
+
183
+ ## Numeric tower and canonical forms
184
+
185
+ Mixed operations promote values through:
186
+
187
+ ```text
188
+ NaturalNumber → Integer → Rational → Polynomial
189
+ ```
190
+
191
+ Canonicalization keeps equivalent representatives predictable:
192
+
193
+ - `Integer.normalize()` moves a pair toward `(a-b, 0)` or `(0, b-a)`;
194
+ - `Rational.reduction()` makes the denominator positive and divides by the GCD;
195
+ - `Polynomial` removes trailing zero coefficients.
196
+
197
+ Equal values have equal hashes even when represented at different levels of the
198
+ numeric tower.
199
+
200
+ ## Scope and limits
201
+
202
+ This project favors definitions that can be read over efficient arithmetic.
203
+ Keep examples small:
204
+
205
+ | Operation | Suggested values |
206
+ | --- | --- |
207
+ | natural-number comparison/addition | 0–10 |
208
+ | natural-number multiplication/division/powers | 0–5 |
209
+ | integer, rational, and polynomial components | absolute values up to 5 |
210
+ | algebraic-root tracing | roughly 12 bisections |
211
+
212
+ `AlgebraicRoot` is deliberately not a complete algebraic-number type. It
213
+ validates one isolated root and shrinks its rational interval, but provides no
214
+ arithmetic between roots and no general mathematical equality.
215
+
216
+ For interval refinement, sign checks use Python's arbitrary-precision integer
217
+ ratios internally. This preserves exactness while avoiding enormous
218
+ intermediate Peano representations; returned endpoints are still `Rational`.
219
+
220
+ ## Documentation development
221
+
222
+ ```bash
223
+ make docs # build Japanese at / and English at /en/
224
+ make docs-serve # preview Japanese
225
+ make docs-serve-en # preview English
226
+ make docs-a11y # run WCAG checks on both languages
227
+ ```
228
+
229
+ The site is deployed from `main` to Cloudflare Workers Static Assets. Deployment
230
+ requires `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` repository secrets.
231
+
232
+ ## Release
233
+
234
+ Releases are built by GitHub Actions and published to PyPI with OpenID Connect.
235
+ The `pypi` GitHub environment must be registered as a PyPI Trusted Publisher
236
+ for this repository and `.github/workflows/publish.yml`.
237
+
238
+ ## License
239
+
240
+ [MIT](LICENSE)
@@ -0,0 +1,213 @@
1
+ # Pythonic Peano Arithmetic
2
+
3
+ An educational Python library that constructs natural numbers, integers,
4
+ rational numbers, and polynomials from simple definitions, then uses rational
5
+ intervals to study algebraic real roots.
6
+
7
+ The implementation is intentionally small and explicit. Its purpose is to make
8
+ the correspondence between a mathematical definition and executable Python
9
+ visible—not to compete with Python's built-in numeric types.
10
+
11
+ The interactive course runs entirely in the browser with Zensical and Pyodide:
12
+
13
+ - [English course](https://peano.yusuke-hayashi.com/en/)
14
+ - [日本語の教材](https://peano.yusuke-hayashi.com/)
15
+
16
+ ## What you can observe
17
+
18
+ - natural numbers built from `0` and the successor operation;
19
+ - recursive definitions of addition and multiplication;
20
+ - integers as equivalence classes of pairs of natural numbers;
21
+ - rationals as equivalence classes of integer pairs;
22
+ - polynomials as finite coefficient sequences;
23
+ - Sturm sequences and bisection over rational isolating intervals;
24
+ - Python mechanisms that connect notation to implementation: special methods,
25
+ decorators, frozen dataclasses, coercion, and operator dispatch.
26
+
27
+ ## Install
28
+
29
+ Python 3.10 or later is required.
30
+
31
+ ```bash
32
+ pip install pythonic-peano-arithmetic
33
+ ```
34
+
35
+ For repository development, install
36
+ [uv](https://docs.astral.sh/uv/) and run:
37
+
38
+ ```bash
39
+ git clone https://github.com/yhay81/pythonic-peano-arithmetic.git
40
+ cd pythonic-peano-arithmetic
41
+ make install
42
+ make check
43
+ ```
44
+
45
+ ## A five-minute tour
46
+
47
+ ### Natural numbers: follow the recursive definition
48
+
49
+ ```python
50
+ from peano import natural_number
51
+ from peano.utils import config_log
52
+
53
+ config_log(log_level=4)
54
+ two = natural_number(2)
55
+ one = natural_number(1)
56
+ print(two + one)
57
+ ```
58
+
59
+ The trace names the rule used at each step:
60
+
61
+ ```text
62
+ [addition: base] add(S(S(0)), 0) -> S(S(0))
63
+ [addition: recursive] add(S(S(0)), S(0)) -> S(add(S(S(0)), 0))
64
+ 3
65
+ ```
66
+
67
+ These two lines correspond directly to:
68
+
69
+ ```text
70
+ n + 0 = n
71
+ n + S(m) = S(n + m)
72
+ ```
73
+
74
+ Pass `locale="ja"` to `config_log` to show Japanese rule labels.
75
+
76
+ ### Integers: equality of representatives
77
+
78
+ An integer is represented by a pair `(a, b)`, read as `a - b`. Different pairs
79
+ can represent the same integer:
80
+
81
+ ```python
82
+ from peano import integer
83
+
84
+ print(integer(3, 1) == integer(4, 2))
85
+ ```
86
+
87
+ The implementation checks the defining equivalence:
88
+
89
+ ```text
90
+ (a, b) ~ (c, d) exactly when a + d = b + c
91
+ ```
92
+
93
+ ### Rationals: equality by cross multiplication
94
+
95
+ ```python
96
+ from peano import rational
97
+
98
+ print(rational(1, 2) == rational(2, 4))
99
+ ```
100
+
101
+ This follows the definition `p/q ~ r/s` exactly when `p*s = q*r`.
102
+
103
+ ### Algebraic real roots: approach √2 with rational intervals
104
+
105
+ ```python
106
+ from peano import Polynomial, Q_ONE, Q_ZERO, algebraic_root, rational
107
+
108
+ x_squared_minus_two = Polynomial(rational(-2, 1), Q_ZERO, Q_ONE)
109
+ root = algebraic_root(x_squared_minus_two, (1, 1), (2, 1))
110
+
111
+ for interval in root.trace(5):
112
+ print(interval)
113
+ ```
114
+
115
+ Every endpoint remains rational. The intervals are nested, their widths halve,
116
+ and each interval still isolates the positive root of `x² - 2`.
117
+
118
+ ## Definition-to-implementation map
119
+
120
+ | Mathematical idea | Python implementation |
121
+ | --- | --- |
122
+ | zero and successor `S(n)` | `NaturalNumber`, `successor` |
123
+ | `0` differs from every successor | `NaturalNumber.__eq__` |
124
+ | successor is injective | `NaturalNumber.__eq__` |
125
+ | `n + 0 = n`, `n + S(m) = S(n + m)` | `NaturalNumber.__add__` |
126
+ | `n × 0 = 0`, `n × S(m) = n + n × m` | `NaturalNumber.__mul__` |
127
+ | `(a,b) ~ (c,d) ↔ a+d=b+c` | `Integer.__eq__` |
128
+ | `p/q ~ r/s ↔ ps=qr` | `Rational.__eq__` |
129
+ | coefficient sequence `(a₀,a₁,...)` | `Polynomial` |
130
+ | distinct roots in an interval | `sturm_sequence`, `count_real_roots` |
131
+ | one algebraic root | `AlgebraicRoot`, `RationalInterval` |
132
+
133
+ Mathematical induction is a proof principle, not a test performed by Python.
134
+ The finite tests check representative laws and guard the intended mapping
135
+ between the definitions and code.
136
+
137
+ ## Logging
138
+
139
+ Operations return ordinary values. Internally, selected methods return a value
140
+ and a lazily constructed explanation; the `@log` decorator exposes only the
141
+ value and emits the explanation when logging is enabled.
142
+
143
+ ```python
144
+ from peano.utils import config_log
145
+
146
+ config_log(
147
+ log_level=4,
148
+ max_lines=200,
149
+ # fmt="Level %(levelno)s: %(message)s", # expose internal levels if needed
150
+ )
151
+ ```
152
+
153
+ Lower log levels reveal more detail. The numeric levels are an internal filter,
154
+ so the default display emphasizes rule names instead.
155
+
156
+ ## Numeric tower and canonical forms
157
+
158
+ Mixed operations promote values through:
159
+
160
+ ```text
161
+ NaturalNumber → Integer → Rational → Polynomial
162
+ ```
163
+
164
+ Canonicalization keeps equivalent representatives predictable:
165
+
166
+ - `Integer.normalize()` moves a pair toward `(a-b, 0)` or `(0, b-a)`;
167
+ - `Rational.reduction()` makes the denominator positive and divides by the GCD;
168
+ - `Polynomial` removes trailing zero coefficients.
169
+
170
+ Equal values have equal hashes even when represented at different levels of the
171
+ numeric tower.
172
+
173
+ ## Scope and limits
174
+
175
+ This project favors definitions that can be read over efficient arithmetic.
176
+ Keep examples small:
177
+
178
+ | Operation | Suggested values |
179
+ | --- | --- |
180
+ | natural-number comparison/addition | 0–10 |
181
+ | natural-number multiplication/division/powers | 0–5 |
182
+ | integer, rational, and polynomial components | absolute values up to 5 |
183
+ | algebraic-root tracing | roughly 12 bisections |
184
+
185
+ `AlgebraicRoot` is deliberately not a complete algebraic-number type. It
186
+ validates one isolated root and shrinks its rational interval, but provides no
187
+ arithmetic between roots and no general mathematical equality.
188
+
189
+ For interval refinement, sign checks use Python's arbitrary-precision integer
190
+ ratios internally. This preserves exactness while avoiding enormous
191
+ intermediate Peano representations; returned endpoints are still `Rational`.
192
+
193
+ ## Documentation development
194
+
195
+ ```bash
196
+ make docs # build Japanese at / and English at /en/
197
+ make docs-serve # preview Japanese
198
+ make docs-serve-en # preview English
199
+ make docs-a11y # run WCAG checks on both languages
200
+ ```
201
+
202
+ The site is deployed from `main` to Cloudflare Workers Static Assets. Deployment
203
+ requires `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` repository secrets.
204
+
205
+ ## Release
206
+
207
+ Releases are built by GitHub Actions and published to PyPI with OpenID Connect.
208
+ The `pypi` GitHub environment must be registered as a PyPI Trusted Publisher
209
+ for this repository and `.github/workflows/publish.yml`.
210
+
211
+ ## License
212
+
213
+ [MIT](LICENSE)
@@ -0,0 +1,66 @@
1
+ """Public API from Peano arithmetic through algebraic-root approximation."""
2
+
3
+ from .algebraic_root import (
4
+ AlgebraicRoot,
5
+ RationalInterval,
6
+ algebraic_root,
7
+ )
8
+ from .integer import Z_MINUS_ONE, Z_ONE, Z_ZERO, Integer, integer, n2z
9
+ from .natural_number import N_ONE, N_ZERO, NaturalNumber, natural_number, successor
10
+ from .polynomial import (
11
+ P_ONE,
12
+ P_ZERO,
13
+ Polynomial,
14
+ count_real_roots,
15
+ n2p,
16
+ polynomial,
17
+ r2p,
18
+ sign_variations,
19
+ sturm_sequence,
20
+ z2p,
21
+ )
22
+ from .rational import (
23
+ Q_MINUS_ONE,
24
+ Q_ONE,
25
+ Q_ZERO,
26
+ Rational,
27
+ n2r,
28
+ rational,
29
+ z2r,
30
+ )
31
+ from .utils import config_log
32
+
33
+ __all__ = [
34
+ "NaturalNumber",
35
+ "natural_number",
36
+ "successor",
37
+ "N_ZERO",
38
+ "N_ONE",
39
+ "Integer",
40
+ "integer",
41
+ "n2z",
42
+ "Z_ZERO",
43
+ "Z_ONE",
44
+ "Z_MINUS_ONE",
45
+ "Rational",
46
+ "rational",
47
+ "n2r",
48
+ "z2r",
49
+ "Q_ZERO",
50
+ "Q_ONE",
51
+ "Q_MINUS_ONE",
52
+ "Polynomial",
53
+ "polynomial",
54
+ "n2p",
55
+ "z2p",
56
+ "r2p",
57
+ "P_ZERO",
58
+ "P_ONE",
59
+ "sturm_sequence",
60
+ "sign_variations",
61
+ "count_real_roots",
62
+ "RationalInterval",
63
+ "AlgebraicRoot",
64
+ "algebraic_root",
65
+ "config_log",
66
+ ]