algebraic-range
Generate ranges of algebraic numbers.
Python port of the Wolfram Language resource function
AlgebraicRange
2.0, by the same author. Requires SymPy ≥ 1.12.
pip install algebraic-range
Overview
algebraic_range creates ranges made of
algebraic numbers:
it extends the basic concept of range() to include, besides rational
numbers, also roots — always restricted to the real domain.
The first two arguments are the bounds of the range, while the optional third and fourth arguments (by default 1 and 0) set the upper and lower bounds of the steps, the differences between successive elements:
algebraic_range(x) # Sqrt[Range[1, x²]], for x ≥ 1
algebraic_range(x, y) # Sqrt[Range[x², y²]], for 0 ≤ x ≤ y
algebraic_range(x, y, s) # steps bounded above by s, 0 < s ≤ y − x
algebraic_range(x, y, s, d) # steps bounded below by d, 0 ≤ d ≤ |s|
If no step is given, the elementary range is the square-root grid anchored
at the bounds — Sqrt[Range[x², y²]] — since among irrationals no constant
step exists. Negative bounds are handled by reflection (real roots are
defined for positive arguments), and a negative s produces a descending
range:
>>> from algebraic_range import algebraic_range
>>> algebraic_range(3)
[1, sqrt(2), sqrt(3), 2, sqrt(5), sqrt(6), sqrt(7), 2*sqrt(2), 3]
>>> algebraic_range(-3, -1)
[-3, -2*sqrt(2), -sqrt(7), -sqrt(6), -sqrt(5), -2, -sqrt(3), -sqrt(2), -1]
With a step upper bound the range is filled by rational multiples of the
elementary roots — conceptually the outer product of
algebraic_range(min(x, x/s), y) with the step-s rational grid,
restricted to [x, y]:
>>> from sympy import Rational
>>> algebraic_range(0, 2, Rational(1, 2))
[0, 1/2, sqrt(2)/2, sqrt(3)/2, 1, sqrt(2), 3/2, sqrt(3), 2]
Taken literally, that outer product scales quadratically; like the Wolfram 2.0 implementation, this port instead selects for each root only the admissible multipliers, by binary search over the sorted factor grid, and effectively scales linearly (see benchmark/BENCHMARK.md).
The fourth argument imposes a minimum absolute difference between successive elements, taming the accumulation of algebraics towards certain points and producing nearly uniform distributions:
>>> algebraic_range(2, 5, Rational(1, 3), Rational(1, 4))
[2, 4*sqrt(3)/3, 2*sqrt(15)/3, 2*sqrt(19)/3, sqrt(10), 2*sqrt(3),
5*sqrt(5)/3, 4, sqrt(19), 8*sqrt(3)/3, 2*sqrt(6)]
Options
| Option | Default | Description |
|---|---|---|
root_order |
2 |
the root orders to be included |
step_method |
"Outer" |
how the step bound is interpreted |
farey_range |
False |
steps given by the Farey sequence |
formula_complexity |
inf |
discard elements above this complexity |
algebraics_only |
True |
accept only algebraic parameters |
working_precision |
machine | precision of internal numerical decisions |
root_order
An integer r includes all roots up to order r; [r] only order r;
[r1, r2, …] all listed orders.
algebraic_range(2, root_order=3) # square and cubic roots
algebraic_range(2, root_order=[3]) # cube roots only:
# [1, 2**(1/3), 3**(1/3), 2**(2/3), 5**(1/3), 6**(1/3), 7**(1/3), 2]
algebraic_range(1, Rational(3, 2), root_order=[3, 5])
step_method
The default "Outer" uses the rational-multiplier construction above;
"Root" steps directly in the power domain,
(Range[x^n, y^n, s^n])^(1/n) — generally a superset:
>>> algebraic_range(0, 2, Rational(2, 3), step_method="Root")
[0, 2/3, 2*sqrt(2)/3, 2*sqrt(3)/3, 4/3, 2*sqrt(5)/3, 2*sqrt(6)/3,
2*sqrt(7)/3, 4*sqrt(2)/3, 2]
farey_range
Generalizes the resource function
FareyRange:
the range combines the algebraic ranges of all steps in the Farey
sequence of the given order (an integer step s means order s; a step
1/n means order n):
>>> algebraic_range(0, 3, Rational(1, 3), farey_range=True) # F₃ steps: 1/3, 1/2, 2/3, 1
equals the union of the plain ranges with steps 1/3, 1/2, 2/3 and 1,
and contains FareyRange[0, 3, 3] as its rational backbone.
formula_complexity
An alternative way to thin a range: discard elements whose symbolic form exceeds a heuristic complexity threshold.
algebraic_range(4, root_order=4, formula_complexity=8)
algebraics_only
By default, transcendental parameters are rejected (NotAlgebraicError);
disable to deliberately allow them:
from sympy import sqrt, E
algebraic_range(0, 5, sqrt(E), algebraics_only=False)
working_precision
With steps below machine resolution, nearby algebraics may collide numerically and be omitted; raising the precision keeps them distinct — it can be pushed arbitrarily high:
algebraic_range(1 - Rational(1, 10**13), 1 + Rational(1, 10**13),
Rational(1, 10**17), working_precision=30)
Behaviour notes
- Approximate inputs are exactified before use (the WL
RootApproximantstep):algebraic_range(0.1, 3.1)starts at1/10. - Results are plain lists of exact SymPy expressions, sorted ascending
(descending for negative
s), without duplicates. - Errors mirror the WL failure modes:
NotRealError,NotAlgebraicError,FareyStepError,LowerBoundError(negatived),StepBoundError(d > |s|).
Performance
The five reference cases of the Wolfram verification suite run in about 1–7 s each (40 000–80 000 elements) — up to ~1.7× faster than the Wolfram Language 2.0 implementation on the stepped cases, and ~40×–100× faster than algebraic-range 0.8. Details and methodology: benchmark/BENCHMARK.md.
Applications
A natural application is the search for closed forms of floating-point
numbers, providing structured search ranges of algebraic candidates.
The sibling package
find-closed-form
(port of the Wolfram resource function
FindClosedForm,
by the same author) accepts these ranges since version 0.5.0 through its
search_range option, searching functions of exact algebraic arguments —
here recovering a formula from its bare machine digits:
from find_closed_form import find_closed_form
find_closed_form(4.1132503787829275, search_range="Algebraic")
# exp(sqrt(2))
Generator options reach algebraic_range through search_range_options
(e.g. {"root_order": 3} to search cube-root arguments), and an explicit
algebraic_range(...) output can be passed as fixed search_arguments.
See also
- Full documentation of the original
AlgebraicRange(contributed by the same author and vetted by the Wolfram Review Team), whose 2.0 verification suite this package transcribes in tests/. - The paclet
GeneralizedRangefor extended functionality and syntax. - The
fareypackage, by the same author, for standalone Farey sequences and ranges. - CHANGELOG.md for the 0.9 rewrite notes.
Metadata
Release files for algebraic-range 0.9.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| algebraic_range-0.9.0.tar.gz | 25.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| algebraic_range-0.9.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.4 kB
Release files / algebraic_range-0.9.0.tar.gz
| Download URL | algebraic_range-0.9.0.tar.gz |
|---|---|
| Size | 25.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dbfeb18154589868dcedc20c1db6d4dcd01fbcd6df4a9bcb6e897549128fb5fd
|
|
BLAKE2b-256 checksum How to use checksums |
db39b7e63b43530e85d29c51588b29e2e144d3bb44dcabeafca10c579bf29938
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Release files / algebraic_range-0.9.0-py3-none-any.whl
| Download URL | algebraic_range-0.9.0-py3-none-any.whl |
|---|---|
| Size | 16.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bdedb438a5ff6155c9a5bc4e96208ff9463de7094f00127b6a4860a6adf2188b
|
|
BLAKE2b-256 checksum How to use checksums |
b992ec432369001b1336a2df5e7b194da1eb98c1c9cca091da91f55c194cfc9b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|