API reference¶
The source of truth for what is public is src/qreals/__init__.py. Everything
below is re-exported from the top-level qreals namespace; anything not listed
here is internal and may change without notice. Each entry is generated from the
docstring in the source.
The two computation paths¶
qreals.rational ¶
The q-rational [p/s]_q as an exact rational function in q.
For a rational the continued fraction terminates, so the MGO formula produces a genuine element of Q(q) rather than a truncated series. This path keeps the result symbolic: q_rational(3, 2) returns (q**2 + q + 1)/(q + 1), not its Taylor coefficients.
Setting q = 1 collapses [n]_q = 1 + q + ... + q^{n-1} back to n, so every q-rational specialises to the ordinary rational at q = 1. The test suite uses that as the defining sanity check.
q_rational ¶
[p/s]_q as a reduced rational function in q, for integers p, s != 0.
Source code in src\qreals\rational.py
q_int ¶
[n]_q for n in Z, as an exact expression in q.
q_int_qinv ¶
[n]_{q^{-1}}, the q -> q^{-1} substitution of [n]_q.
qreals.truncated ¶
The q-real [x]_q as a truncated power series, for any real x.
This is the path for irrationals (pi, sqrt(2), the golden ratio) and for any
input where the exact rational function is not wanted. The MGO formula is
evaluated bottom-up over the truncated-series kernel in series, so the
result is the first N stable integer Taylor coefficients of [x]_q.
For a rational p/s the CF terminates and this returns the Taylor expansion of
the exact function computed in rational; the two agree coefficient for
coefficient, which the test suite checks.
q_real_truncated ¶
First N stable Taylor coefficients of [x]_q.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x_repr
|
str
|
a sympy-parseable string, e.g. "pi", "sqrt(2)", "(1+sqrt(5))/2", "E", "3/2". |
required |
N
|
int
|
number of stable coefficients required, per MGO Proposition 1.1. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
A list of N integers [c_0, c_1, ..., c_{N-1}], where c_k is the |
list[int]
|
coefficient of q^k. |
Source code in src\qreals\truncated.py
The module symbol qreals.q is the sympy symbol used in the rational-function
results of q_rational.
Arithmetic between q-reals¶
qreals.arithmetic ¶
Arithmetic between q-reals: series sum, series product, and q-negation.
The stable core here works on coefficient lists over the truncated-series kernel
in series, so it stays pure Python (sympy is used only to read the continued
fraction of x, through q_real_truncated). Three things live here, with one
caveat each, all spelled out in docs/CORRECTNESS.md:
-
q_add(x, y, N)andq_mul(x, y, N)return the first N Taylor coefficients of the series sum [x]_q + [y]_q and the series product [x]_q * [y]_q. These are the sum and product of the two q-series, NOT [x+y]_q or [x*y]_q: the MGO map x |-> [x]_q is not a ring homomorphism.gosperreaches the same two quantities by a different algorithm, which the tests use as a cross-check. -
q_neg(x, N)returns the q-deformed negation [-x]_q of Jouteur (arXiv:2503.02122, eq. 2), as a Laurent result (valuation, coeffs). This is the PGL_2(Z)-action negation, which is NOT the coefficient-wise negation of [x]_q and NOT the MGO series of the real number -x. It is an involution, andnegation_sum/finite_xnegxuse it to study Ovsienko's Example 6.4 (for which real x is [x]_q + [-x]_q a finite Laurent polynomial). -
radius(x, N)estimates the radius of convergence of the power series [x]_q from its first N coefficients, by the running-max root-test slope. The finite-N value is biased high; see its docstring and the docs.
q_add ¶
First N Taylor coefficients of the series sum [x]_q + [y]_q (x, y >= 0).
This is the coefficient-wise sum of the two q-series. It is verified against
the bihomographic gosper engine, an independent algorithm, on rationals.
Source code in src\qreals\arithmetic.py
q_mul ¶
First N Taylor coefficients of the series product [x]_q * [y]_q (x, y >= 0).
This is the Cauchy product (convolution) of the two q-series, cross-checked
against the gosper engine's "mul" value on rationals.
Source code in src\qreals\arithmetic.py
q_neg ¶
The Jouteur q-negation [-x]_q (x >= 0) as (valuation, N coefficients).
[-x]_q is a Laurent series (it carries negative powers of q), so the result is returned as a valuation together with the coefficient list from q^v up.
Source code in src\qreals\arithmetic.py
negation_sum ¶
[x]_q + [-x]_q (x >= 0) as (valuation, N coefficients), Ovsienko Ex. 6.4.
Source code in src\qreals\arithmetic.py
finite_xnegx ¶
Does [x]_q + [-x]_q terminate as a finite Laurent polynomial? (Ex. 6.4)
Computed numerically to the given order: the sum is reported finite when its coefficients past the leading block are a long run of zeros. The proven criterion (finite iff x is a trace-zero quadratic, i.e. a pure square root) and the closed identity behind it are in docs/CORRECTNESS.md; this is the operational check, honest about being a finite-order observation.
Source code in src\qreals\arithmetic.py
radius ¶
Running-max root-test estimate of the radius of convergence of [x]_q.
The Cauchy-Hadamard radius is R = 1 / limsup_k |c_k|^{1/k}. This returns the finite-N reciprocal of the running maximum of |c_k|^{1/k} over 1 <= k < N, i.e. exp(-max_k (ln|c_k|) / k). Returns +inf only when no coefficient past the constant term is nonzero in the window (x = 0 or x = 1).
Finite-N bias, stated honestly: the running maximum over a finite window is at most the true limsup, so this estimate is at least the true radius. It is biased high and decreases toward R from above as N grows. For an integer x, where [x]_q is a polynomial (true radius infinite), the low-order unit coefficients pin the estimate near 1 rather than revealing the infinite radius; that saturation is itself a face of the finite-N bias.
Source code in src\qreals\arithmetic.py
qreals.qreal ¶
QReal: a convenience wrapper around a computed q-real series.
The functional API in arithmetic and truncated is the stable core; this
class is sugar over it. A QReal holds a Laurent result (a valuation and a dense
coefficient list) together with a short label saying where it came from, and
offers the everyday read-outs plus operators that delegate straight back to the
functions:
QReal("pi", 12).coeffs -> [1, 1, 1, 0, ...]
QReal("3/2", 12) + QReal("13/5") -> q_add, a new QReal
-QReal("sqrt(2)", 12) -> q_neg (Jouteur), a Laurent QReal
QReal("3/2", 12) * QReal("5/2") -> q_mul, a new QReal
Operators carry the same caveats as the functions they call: + and * are the series sum and product [x]_q +/ [y]_q, not [x +/ y]_q, and unary - is the Jouteur PGL_2(Z) negation [-x]_q, not coefficient negation. See docs/CORRECTNESS.md.
QReal ¶
A q-real [x]_q held to N coefficients, with read-outs and operators.
Source code in src\qreals\qreal.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
lowest_power
property
¶
The exponent of the first stored coefficient (the valuation).
__init__ ¶
Build [x]_q for real x >= 0, keeping its first N Taylor coefficients.
Source code in src\qreals\qreal.py
from_laurent
classmethod
¶
Wrap an already-computed (valuation, coeffs) Laurent result.
Source code in src\qreals\qreal.py
radius_estimate ¶
Running-max root-test estimate of the radius of convergence.
Defined only for a Taylor q-real (valuation 0); a negated/Laurent QReal
has no power-series radius, so this raises. Delegates to
arithmetic.radius via the coefficient list it already holds.
Source code in src\qreals\qreal.py
sign_pattern ¶
zero_run ¶
The longest run of consecutive zero coefficients as (start, length).
start is the index into coeffs (so the power is valuation + start);
length is 0 when there is no zero coefficient. The first such longest run
is reported on a tie.
Source code in src\qreals\qreal.py
The bihomographic cross-check engine¶
qreals.gosper ¶
The q-deformed bihomographic engine, an independent route to q-real arithmetic.
This is the q-analogue of the classical bihomographic continued-fraction state machine (a "Gosper" engine). The classical engine carries a 2x4 integer state and ingests partial quotients of x and y by right-multiplying by the Kronecker-factored blocks A(t) (x) I and I (x) A(t), with the continued-fraction block A(t) = [[t, 1], [1, 0]]. Here every entry is promoted to its MGO q-deformed counterpart, so the state carries Laurent polynomials in q and the engine computes a bilinear function of the q-reals [x]_q and [y]_q directly from the continued fractions of x and y.
The MGO q-block, in the exact regular-CF convention rational and truncated
use. For an even-length regular continued fraction a = [a_1, ..., a_{2m}],
A_q^{(i)}(a) = [[ [a]_q , q^{ a} ], [1, 0]] at odd positions (1-indexed),
[[ [a]_{1/q}, q^{-a} ], [1, 0]] at even positions,
and [x]_q = R_x / S_x where (R_x, S_x)^T is the first column of the product of the blocks. With monomial columns (XY, X, Y, 1) the 2x4 state S = [[a,b,c,d],[e,f,g,h]] represents z(X, Y) = (aXY+bX+cY+d)/(eXY+fX+gY+h). Ingesting an x-quotient right-multiplies by A_q (x) I; a y-quotient by I (x) A_q. After full ingestion the first-column ratio of S . (prod P_q)(prod Q_q) is z([x]_q, [y]_q): for op="add" that is [x]_q + [y]_q, for op="mul" it is [x]_q * [y]_q.
Why this is here. arithmetic.q_add and arithmetic.q_mul compute the same
quantities the cheap way, by expanding each q-real series and adding or
convolving the coefficient lists. This engine reaches the result by a different
algorithm (a state machine over rational functions in q, never forming the two
series separately), so agreement between the two is a real cross-check rather
than a re-run of one code path. The test suite uses it exactly that way; see
docs/CORRECTNESS.md.
Caveat (the load-bearing one). For op="add" this computes [x]_q + [y]_q, the sum of the two q-series, NOT [x+y]_q, the q-deformation of the real sum. The MGO map x |-> [x]_q is not additive, so these differ already at q^0 (constant term 2 vs 1); the deficit D = [x+y]_q - ([x]_q + [y]_q) is a separate object and is not what this engine returns.
q_gosper ¶
z([x]_q, [y]_q) as a reduced rational function in q, via the 2x4 state.
op="add" gives [x]_q + [y]_q; op="mul" gives [x]_q * [y]_q. Inputs are rationals (the continued fraction must terminate for the state to close).
Source code in src\qreals\gosper.py
gosper_coeffs ¶
First N Taylor coefficients [c_0..c_{N-1}] of z([x]_q, [y]_q).
For x, y > 0 both q-reals are regular at q = 0 and the result is a Taylor series, so the valuation is taken to be 0.
Source code in src\qreals\gosper.py
Verification stamp¶
qreals.verify ¶
Inline cross-checks for a qreals result, the everyday trust signal.
After every computation qreals runs the cheap checks that apply to that input and prints one line, for example::
verified: q=1 matches 3/2, exact = truncated to 12
This module is core. It imports only sympy and the other core modules, never
the interface or the certificate layer, so the stamp works with pip install
qreals alone and never needs a TeX engine. It writes nothing.
Each check recomputes a value a second, independent way and compares:
- q=1 specialisation. For a rational input, setting q=1 collapses [n]_q back to n, so [p/s]_q at q=1 must equal the ordinary p/s (RAT Corollary 1.7).
- exact = truncated. For a rational input the continued fraction terminates,
so the truncated series must equal the Taylor expansion of the exact
rational function computed by
q_rational. - truncation stable. The first N coefficients of [x]_q must not change when more are requested (REAL Theorem 1).
- shift law. [x+1]_q = q [x]_q + 1 (REAL eqn 3). Recomputing [x+1]_q from its own continued fraction and comparing to q*[x]_q + 1 is an algorithm-level cross-check that holds for every real x.
For an irrational input the first two checks cannot run (there is no terminating rational function and the series diverges at q=1); the stamp says so plainly rather than claiming a pass.
The mathematics follows Morier-Genoud and Ovsienko, "q-deformed rationals and q-continued fractions", Forum Math. Sigma 8 (2020); see docs/CORRECTNESS.md.
Stamp
dataclass
¶
The set of checks run for one computation, plus the one-line summary.
Source code in src\qreals\verify.py
line ¶
The one-line stamp, honest about what did and did not run.
Source code in src\qreals\verify.py
verify ¶
Run the cross-checks that apply to a computation result dict.
Dispatches on result["kind"]. An unknown or absent kind (the help screen, say) yields an empty stamp, which renders as no line at all.
Source code in src\qreals\verify.py
Laurent expansions and the board lemmas¶
qreals.expansions ¶
May-14 board lemmas about q-real Laurent expansions, as first-class functions.
Four lemmas from the Qnumbers01 board (q-numbers vault, may14/), each turned into a tested function:
-
Integer-part prefix. For real x with t = floor(x), the Laurent expansion of [x]_q opens with [t]_q = 1 + q + ... + q^{t-1} and then a forced 0 coefficient at q^t, the clean seam between integer and fractional parts.
integer_part_prefix. (note 1) -
Convergents pin down coefficients. For a positive irrational x with continued fraction [a_1, a_2, ...] and partial sum S_n = a_1 + ... + a_n, the n-th convergent computes [x]_q correctly on a known number of low powers.
coeffs_locked_by_convergent. (note 2) -
The MGO positive form. [x]_q is the Laurent expansion produced by the MGO continued-fraction formula;
mgo_laurentreads its coefficients off to a requested order. (note 3) -
The shift relations. [x-1]_q = ([x]_q - 1)/q lowers the argument by one and [x+1]_q = q[x]_q + 1 raises it.
shift_downandshift_upare the tool that moves a coefficient question between unit intervals. (note 5)
CLI
python -m qreals.expansions pi --order 12
prints the Laurent expansion of [x]_q to the requested order plus its forced integer-part prefix.
integer_part_prefix ¶
The forced opening block [floor(x)]_q + 0*q^floor(x) of [x]_q (note 1).
For real x with t = floor(x), the Laurent expansion of [x]_q begins with t coefficients all equal to 1 (spelling out [t]_q) followed by a 0 coefficient at q^t. This returns that prefix as a list of t + 1 integers, [1, 1, ..., 1, 0]; the fractional part of x can perturb only powers q^{t+1} and higher.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
str | int | float | Expr
|
a sympy-parseable real, e.g. "22/7", "pi", 3, "pi-2". |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
[1] * t + [0], where t = floor(x). |
Source code in src\qreals\expansions.py
coeffs_locked_by_convergent ¶
How many Laurent coefficients the n-th convergent of x locks in (note 2).
With continued fraction x = [a_1, a_2, ...] and partial sum S_n = a_1 + ... + a_n, the n-th convergent x_n agrees with [x]_q on every power strictly below q^{S_n - 1}. Returns (S_n, count), where count = S_n - 1 is the number of locked coefficients, i.e. the powers q^0, ..., q^{S_n - 2}. The first power that may differ is q^{S_n - 1}.
Note on the off-by-one. Note 2 phrased the cutoff as "below q^{S_n}", which
would make count = S_n. Direct computation refutes that: for x = pi,
a_1 = 3, a_2 = 7, S_2 = 10, the convergent [3,7] = 22/7 gives
[22/7]_q = 1 + q + q^2 + q^9 + ... whereas the true [pi]_q has a 0 at q^9
(its next term is at q^10). So [22/7]_q and [pi]_q already differ at
q^9 = q^{S_2 - 1}: agreement holds only below q^{S_n - 1}, locking S_n - 1
coefficients, not S_n. This matches the existing continued_fraction
docstring and is the resolution of the numerical tension flagged in note 5.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cf_terms
|
Sequence[int]
|
the continued-fraction partial quotients [a_1, a_2, ...]. |
required |
n
|
int
|
convergent index, 1 <= n <= len(cf_terms). |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
(S_n, count) with S_n = a_1 + ... + a_n and count = S_n - 1. |
Source code in src\qreals\expansions.py
mgo_laurent ¶
Laurent coefficients of [x]_q through q^order, via the MGO formula (note 3).
Evaluates the MGO positive-form continued fraction for x over the truncated-series kernel and reads off the coefficients of q^0 up to and including q^order. Returns order + 1 integers [c_0, ..., c_order] with c_k the coefficient of q^k. For x >= 1 the series has valuation 0 (c_0 = 1); for 0 < x < 1 it has valuation 1 (c_0 = 0).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
str | int | float | Expr
|
a sympy-parseable real, e.g. "22/7", "pi", "sqrt(2)". |
required |
order
|
int
|
highest power q^order to return; must be >= 0. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
[c_0, c_1, ..., c_order]. |
Source code in src\qreals\expansions.py
shift_down ¶
Coefficients of [x-1]_q = ([x]_q - 1)/q from those of [x]_q (note 5).
Subtracts 1 from the constant term and divides by q, i.e. drops the constant coefficient and shifts every higher power down by one. This is exact only when the constant term is 1, which holds for any [x]_q with x >= 1 (the integer-part lemma forces it); a different constant term means the input is not such a series, so the division by q would produce a negative power, and this raises.
Returns one fewer coefficient than the input (the top power is lost to the division, matching the precision the truncated series can support).
Source code in src\qreals\expansions.py
shift_up ¶
Coefficients of [x+1]_q = q[x]_q + 1 from those of [x]_q (note 5).
Multiplies by q and adds 1: the new constant term is 1 and every old
coefficient moves up one power. Inverse of shift_down. Returns one more
coefficient than the input.
Source code in src\qreals\expansions.py
format_laurent ¶
Render a coefficient list [c_0, c_1, ...] as a readable q-polynomial.
Appends an O(q^N) tail where N = len(coeffs), the first power not held.
Source code in src\qreals\expansions.py
Coefficient read-outs¶
qreals.coefficients ¶
Small read-outs over a coefficient list produced by q_real_truncated.
These answer the questions that come up when looking for patterns in the Taylor coefficients of a q-real: where does the first nonzero term sit, where does the first sign change happen, how large do the coefficients get.
Exploration helpers (optional extras)¶
qreals.features ¶
A named, fixed-length fingerprint of a real number's q-analog.
featurize(x) turns a real number x into a vector of named, deterministic
features drawn from two sources: the regular continued fraction of x (which
drives the MGO construction) and the integer Taylor coefficients of its q-analog
[x]_q. The vector is fixed length for a given set of parameters, so two
constants are directly comparable: the point is exploration and nearest-neighbour
search over constants, not training a model.
The output is a :class:Fingerprint: a parallel pair of names and values
(plain floats), with as_dict() for a name -> value mapping and as_numpy()
for a numpy array when numpy is installed. No numpy is needed to build a
fingerprint or to compare two of them; numpy is the only optional dependency,
behind the qreals[features] extra, and is used only by as_numpy. There is
no torch and no model here.
The features, in the order they appear in the vector:
Scalar features (16):
valuation: index of the first nonzero coefficient of [x]_q. 0 for x >= 1, 1 for 0 < x < 1.n_zeros: how many of the firstn_coeffscoefficients are zero.longest_zero_run: length of the longest run of consecutive zero coefficients in that window.first_negative_index: index of the first negative coefficient, orn_coeffsif none is negative in the window.n_sign_changes: sign changes between consecutive nonzero coefficients.n_sign_runs: number of maximal same-sign runs over the nonzero coefficients (n_sign_changes + 1, or 0 when all coefficients are zero).longest_sign_run: the longest such run.max_abs_coeff: the largest |c_k| in the window.mean_abs_coeff: the mean of |c_k| over the window.log10_max_abs_coeff:log10(1 + max_abs_coeff), a scale-insensitive measure of how big the coefficients get.log10_mean_abs_coeff:log10(1 + mean_abs_coeff).inv_radius: the running-max root-test slopemax_k (ln|c_k|)/kover the firstn_radiuscoefficients. This is 1 / (radius-of-convergence estimate); it is 0 exactly when [x]_q is a polynomial (x a nonnegative integer), and larger when the coefficients grow faster. Always finite, unlike the radius itself, which is what makes it usable as a coordinate.cf_len: number of regular continued-fraction terms actually available, up ton_cf(a terminating, i.e. rational, expansion shows up as cf_len < n_cf).cf_max: the largest partial quotient among the firstn_cfterms.cf_sum: the sum of the firstn_cfpartial quotients (its growth sets how fast coefficients lock in, MGO Proposition 1.1).
Block features:
cf_0 .. cf_{n_cf-1}: the partial quotients (continued-fraction terms) of x, padded with 0 past a terminating expansion.cf_0is floor(x).cf_partial_sum_1 .. cf_partial_sum_{n_cf}: cumulative sums of those partial quotients. A plateau marks where a rational expansion terminated.c_0 .. c_{n_coeffs-1}: the signed integer Taylor coefficients of [x]_q, the most direct fingerprint of the series. These can grow large for some constants, so for scale-insensitive nearest-neighbour either normalise the vector or lean on the log-magnitude and shape scalars above.
All features are derived from exact integer coefficients and the exact symbolic
continued fraction, so featurize is deterministic: the same x and parameters
give the same vector every time.
Fingerprint
dataclass
¶
A named, fixed-length feature vector for one real number.
names and values are parallel lists of the same length. x is the
input as given, and params records (n_cf, n_coeffs, n_radius) so two
fingerprints are only comparable when their params agree.
Source code in src\qreals\features.py
as_dict ¶
as_numpy ¶
The values as a numpy float array (needs qreals[features]).
Source code in src\qreals\features.py
featurize ¶
featurize(
x: str | int | float | Expr,
*,
n_cf: int = DEFAULT_N_CF,
n_coeffs: int = DEFAULT_N_COEFFS,
n_radius: int = DEFAULT_N_RADIUS,
) -> Fingerprint
A named, fixed-length, deterministic fingerprint of [x]_q.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
str | int | float | Expr
|
a sympy-parseable real, e.g. "pi", "sqrt(2)", "(1+sqrt(5))/2", "3/2". |
required |
n_cf
|
int
|
how many continued-fraction terms (and their partial sums) to keep. |
DEFAULT_N_CF
|
n_coeffs
|
int
|
how many signed Taylor coefficients of [x]_q to keep. |
DEFAULT_N_COEFFS
|
n_radius
|
int
|
window for the |
DEFAULT_N_RADIUS
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
Fingerprint
|
class: |
Fingerprint
|
parameters, so fingerprints built with the same parameters are directly |
|
Fingerprint
|
comparable (see :func: |
The math each feature reads is documented at the top of this module.
Source code in src\qreals\features.py
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | |
feature_names ¶
feature_names(
n_cf: int = DEFAULT_N_CF,
n_coeffs: int = DEFAULT_N_COEFFS,
n_radius: int = DEFAULT_N_RADIUS,
) -> list[str]
The fixed feature names, in vector order, for the given parameters.
Source code in src\qreals\features.py
feature_distance ¶
Euclidean distance between two fingerprints (same parameters required).
The raw coefficient features can dominate this distance for fast-growing constants; normalise the vectors first if you want a shape-based comparison.
Source code in src\qreals\features.py
nearest ¶
nearest(
target: Fingerprint,
pool: Sequence[Fingerprint],
k: int = 1,
) -> list[tuple[Fingerprint, float]]
The k fingerprints in pool closest to target by Euclidean distance.
Returns (fingerprint, distance) pairs sorted nearest first. A small helper
for nearest-neighbour exploration over a set of constants.
Source code in src\qreals\features.py
qreals.oeis ¶
Look a coefficient sequence up in the OEIS, with re-verification.
A q-series produces an integer coefficient sequence; the obvious next question
is whether that sequence is already catalogued. This module submits a sequence
to the OEIS public API (oeis.org/search), ranks the hits by matching-prefix
length (reconciling a handful of sign conventions, since a q-series can arrive
negated or alternating relative to the canonical unsigned entry), re-verifies
each top hit against its full b-file so a deep divergence such as "matched the
first 20 terms but diverged at term 25" is surfaced, and also tries mod-p
reductions of the input. Every HTTP response is cached on disk so re-running the
same sequence does not hit the network again.
This is an optional helper. The only network dependency is requests, behind
the qreals[oeis] extra; the rest of qreals does not import it. Two failure
modes are handled without crashing:
requestsnot installed:lookupraises :class:OeisUnavailable, a clear error pointing atpip install qreals[oeis]. Test with :func:available.- the network is down or OEIS is unreachable: each query fails quietly and the
lookup returns an empty :class:
LookupResult(no hits) rather than raising.
Adapted from the standalone qoeis tool. The math context (q-Taylor and
q-continued-fraction coefficient sequences) is the same one the rest of qreals
computes.
LookupResult
dataclass
¶
Hit
dataclass
¶
Source code in src\qreals\oeis.py
OeisUnavailable ¶
lookup ¶
lookup(
sequence: str | Sequence[int],
*,
primes: Sequence[int] = DEFAULT_PRIMES,
max_hits: int = 10,
bfile_top: int = 3,
do_modp: bool = True,
do_bfile: bool = True,
cache_dir: str | Path | None = None,
session: Any = None,
timeout: int = DEFAULT_TIMEOUT,
max_workers: int = 6,
) -> LookupResult
Look up sequence in the OEIS.
sequence may be a string ("1,1,2,5,...") or any iterable of ints.
Returns a :class:LookupResult whose hits are ranked by matching-prefix
length (sign-reconciled), with the top bfile_top hits re-verified against
their full b-files, plus modp_hits for the mod-p reductions of the input.
Needs the requests dependency (pip install qreals[oeis]); raises
:class:OeisUnavailable if it is missing. If OEIS is unreachable, every
query fails quietly and the result carries no hits.
Source code in src\qreals\oeis.py
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 | |