Open the live app, no install needed, to compute q-numbers exactly in the browser.
A q-number replaces an ordinary number x with a series in a variable q that
collapses back to x at q = 1. qreals computes these exactly, and ships a
browser app to explore them.
Each number in this table is recomputed by tests/test_docs.py, so a stale
value fails the test suite in CI.
| Python modules | 56 (find src -name "*.py" | wc -l) |
| Tests | 1160 (python -m pytest --collect-only -q) |
| Python versions | 3.11, 3.12, 3.13 (pyproject.toml classifiers, CI matrix) |
| MCP tools | 10 (qreals mcp) |
| CLI subcommands | 46 (qreals --help) |
The MCP server (qreals mcp) exposes 10 typed tools and 3 read-only catalog resources describing the tool routing, input grammar, and verdict vocabulary. Every tool is a thin wrapper over an existing engine function (src/qreals/mcp_server.py:7), so the numbers an MCP client sees are the same numbers the CLI and the test suite see. A failing call returns a structured payload (error category, whether it is retryable, and a remedy) instead of a bare traceback.
The test suite checks the engine against values printed by Morier-Genoud
and Ovsienko (q-rationals such as 5/2, 5/3 and 7/5; the first 21 to 80
Taylor coefficients of the golden ratio, the silver ratio, sqrt(2), sqrt(3),
sqrt(5), sqrt(7), e and pi) and against OEIS A004148. It also checks the
identities [x+1]_q = q[x]_q + 1 and [-1/x]_q = -1/(q[x]_q) and the
q = 1 specialization on a grid of rationals, negatives included, and total
positivity on rationals above 1. The engine must also agree with the
negative continued fraction formula, which the tests implement on their
own, and its alternative code paths must agree with each other.
Property-based tests (Hypothesis) repeat the identities on random bounded
rationals. Mutation testing measures how many injected bugs in the core
math modules the suite catches. docs/VERIFICATION.md
lists every check, what it proves and what it does not, how to rerun it,
and the current results.
See docs/HOW-IT-WORKS.md for a from-zero explanation of the math, the package architecture, and a module-by-module walkthrough.
The live app above covers most visitors. To run qreals locally, as a CLI, a Python library, or an MCP server, install it with pip.
You need Python 3.11 or newer. Check with python --version (Windows) or
python3 --version (macOS). If you do not have it, install it first from
python.org (on Windows, tick "Add Python
to PATH" in the installer).
Windows (PowerShell):
py -m pip install qrealsmacOS (Terminal):
python3 -m pip install qrealsqreals serveThis starts a local server and opens the app in your browser at
http://127.0.0.1:8000. Use qreals serve --port 9000 to pick a different
port, or qreals serve --no-browser to skip opening a window. Press
Ctrl+C in the terminal to stop it.
Re-run the install command with --upgrade to get the newest release:
Windows:
py -m pip install --upgrade qrealsmacOS:
python3 -m pip install --upgrade qrealsPrefer the source? Download the repo as a ZIP from the green Code button on GitHub (or clone it), then run
pip install .from inside the folder.
For a fraction p/s you get an exact rational function [p/s]_q, and for any
real x you get the exact integer coefficients of its power series [x]_q, to
any length. The math is from Morier-Genoud and Ovsienko, "q-deformed rationals
and q-continued fractions" (Forum Math. Sigma, 2020). The truncated-series
path folds the continued fraction with polynomial multiplications and one
final long division, measured about 300x faster at depth 512 than the
inversion-per-term fold it falls back to.
Every feature below is reachable three ways: a Python function, a qreals
subcommand (add --json for machine output), and a card in qreals serve.
q-rationals
| Feature | What it does |
|---|---|
Exact q-rational [p/s]_q |
The exact rational function in q for a fraction p/s. |
q-integer [n]_q |
The q-analog of a whole number, [n]_q and [n]_{1/q}. |
| Factor R(q), S(q) | Factor numerator and denominator of [a/b]_q over Z[q], labelling each cyclotomic factor. |
| Roots of R(q) | Plot the complex roots of R(q) on the unit circle, splitting cyclotomic roots from the core. |
| Jump gap | The right and left q-versions of p/s and the factored gap between them. |
Denominator dossier qreals denom a/d |
One screen per fraction: S(q) expanded and factored, the cyclotomic index set T, deg S vs d-1, the S(1) = d check, the class (FULL / COLLAPSE / REPEATED / NONCYC), a^2 mod d, and every coprime split d = d+ d- with its discrepancy classified EXACT, POLYNOMIAL, or RATIO. Flags: --json, --tex. |
Reverse table qreals collapse d |
The dossier mapped over every numerator coprime to d, grouped by identical S: index set T, factored S, residues per prime-power part of d, realized splits with discrepancy class, RATIO numerators flagged, and the c(d) / non-cyclotomic counts. --range d1..d2 emits the c(d) sequence one line per d, ready to pipe into qreals oeis. Flags: --json, --tex. |
Conjecture falsifier qreals conj NAME |
A registry of falsifiable conjectures (divisor, sqrt-law, indices-2ju, mult-two, floor3, negsum-period) scanned counterexample-first: the run stops at the FIRST counterexample, prints its full dossier, and exits 1; a survivor reports the range covered, the instance count, the wall time, and the three nearest misses by the entry's registered metric, exiting 0. Long scans checkpoint every 60 seconds and continue with --resume. qreals conj list prints the registry with each statement. Flags: --until N, --resume, --state FILE, --json. |
q-reals
| Feature | What it does |
|---|---|
Coefficients [x]_q |
The first N Taylor coefficients of [x]_q for any real x. |
| Laurent expansion | [x]_q written out to a chosen power, with its integer-part prefix. |
| Integer-part prefix | The forced opening block of [x]_q fixed by floor(x). |
| Convergent locking | How many coefficients the n-th convergent of x pins down. |
Shift by one [x ± 1]_q |
[x+1]_q = q[x]_q + 1, [x-1]_q = ([x]_q - 1)/q. |
| Coefficient read-outs | First nonzero, first negative, largest size, zero count. |
| Radius of convergence | A running-max estimate of the radius of convergence of [x]_q. |
| Fingerprint | A named, fixed-length feature vector of [x]_q for nearest-neighbour. |
| Certificate | The coefficients of [x]_q with a ready-to-paste LaTeX table. |
Arithmetic (via the q-Gosper engine)
| Feature | What it does |
|---|---|
q-sum [x]_q + [y]_q |
The series sum of the two q-reals. |
q-product [x]_q · [y]_q |
The series product of the two q-reals. |
| Deficit | How far [x]_q +/* [y]_q sits from [x +/* y]_q, with the q=1 and q=0 checks. |
Symmetry
| Feature | What it does |
|---|---|
q-negation [-x]_q |
The Jouteur negation [-x]_q and the x → −x symmetry. |
| Negation-sum finiteness | Whether [x]_q + [-x]_q is a finite Laurent polynomial. |
Visuals (in qreals serve)
| Feature | What it does |
|---|---|
| Coefficient landscape | A 3D surface of the Taylor coefficients of [x]_q as n and x vary. |
| Root migration | The complex roots of R(q) as the denominator sweeps. |
| Radius landscape | The radius of convergence of [a/b]_q over a Farey grid. |
| Conway-Coxeter frieze | The frieze of a/b > 1 with the q-coefficient overlay on every cell. |
Lookup
| Feature | What it does |
|---|---|
| OEIS lookup | Look a coefficient sequence up in the OEIS, re-verified against the b-file. |
$ qreals denom 19/60
fraction in lowest terms: 19/60
continued fraction: [0; 3, 6, 3]
S(q) factored = Phi_2 * Phi_3 * Phi_4 * Phi_5 * Phi_6
class: COLLAPSE
60 = 3 * 20 RATIO (Phi_10 Phi_20) / Phi_6
$ qreals conj floor3 --until 24
conjecture: floor3
statement: The q-continuant is injective on tails whose entries are all at least 3.
range covered: tails with entries >= 3 and entry sum <= 24, ascending sum then lexicographic
instances checked: 5895
...
verdict: survives the scanned range
qreals denom --help and qreals conj --help carry full worked examples with
their exact output; tests/test_cli.py runs each example command and
requires its output to equal the example byte for byte, so the documentation
cannot drift from the tools.
Each section below is generated from the tool's own --help worked example
by python -m qreals.readme, so it is always the literal output of the
current code.
One-shot denominator dossier of [a/d]_q.
worked example:
$ qreals denom 4/15 --json
{
"a": 4,
"d": 15,
"cf": [
0,
3,
1,
3
],
"k": 3,
"N": "1 + q + q^2 + q^3",
"S": "1 + 2*q + 3*q^2 + 3*q^3 + 3*q^4 + 2*q^5 + q^6",
"S_factored": "Phi_3 * Phi_5",
"T": [
3,
5
],
"multiplicities": {
"3": 1,
"5": 1
},
"noncyclotomic_cofactor": null,
"is_cyclotomic_product": true,
"saturation_index": 15,
"minimal_saturating_n": 15,
"deg_S": 6,
"deg_bound": 14,
"S_at_1": 15,
"S_at_1_ok": true,
"klass": "COLLAPSE",
"a_sq_mod_d": 1,
"splits": [
{
"d_plus": 1,
"d_minus": 15,
"realized": false,
"discrepancy_class": "POLYNOMIAL",
"discrepancy": "Phi_15"
},
{
"d_plus": 3,
"d_minus": 5,
"realized": true,
"discrepancy_class": "EXACT",
"discrepancy": "1"
}
]
}
Cyclotomic reference card of [n]_q: every factor expanded, deg = phi(e), value at 1, prime-power vs composite divisors.
worked example:
$ qreals bricks 12 --json
{
"n": 12,
"qint": "1 + q + q^2 + q^3 + q^4 + q^5 + q^6 + q^7 + q^8 + q^9 + q^10 + q^11",
"rows": [
{
"e": 2,
"phi": "1 + q",
"deg": 1,
"phi_at_1": 2
},
{
"e": 3,
"phi": "1 + q + q^2",
"deg": 2,
"phi_at_1": 3
},
{
"e": 4,
"phi": "1 + q^2",
"deg": 2,
"phi_at_1": 2
},
{
"e": 6,
"phi": "1 - q + q^2",
"deg": 2,
"phi_at_1": 1
},
{
"e": 12,
"phi": "1 - q^2 + q^4",
"deg": 4,
"phi_at_1": 1
}
],
"prime_powers": [
2,
3,
4
],
"composites": [
6,
12
],
"lcm": null,
"at": null
}
Conjecture falsifier: scan a registered conjecture for its first counterexample, or 'list' the registry.
worked example:
$ qreals conj list --json
{
"conjectures": [
{
"name": "divisor",
"statement": "Every cyclotomic index of the denominator S of a reduced fraction a/d divides d.",
"space": "reduced fractions a/d up to denominator N",
"miss_metric": "minus the degree of the non-cyclotomic cofactor of S (more non-cyclotomic mass = nearer)",
"default_until": 60
},
{
"name": "sqrt-law",
"statement": "If every root of the denominator S of a reduced fraction a/d is a root of unity, then a^2 = 1 (mod d).",
"space": "reduced fractions a/d up to denominator N",
"miss_metric": "degree of the non-cyclotomic part of S among instances with a^2 != 1 (mod d) (smaller = nearer)",
"default_until": 60
},
{
"name": "indices-2ju",
"statement": "Every cyclotomic index in the product-law discrepancy [d+]_q [d-]_q / S of a realized coprime split d = d+ d- has the form 2^j u with u odd and j >= 1.",
"space": "reduced fractions a/d up to denominator N",
"miss_metric": "least 2-adic valuation among the discrepancy indices (valuation 1 = nearest to an odd index)",
"default_until": 60
},
{
"name": "mult-two",
"statement": "No cyclotomic factor of the denominator S of any reduced fraction appears with multiplicity above 2.",
"space": "reduced fractions a/d up to denominator N",
"miss_metric": "3 minus the largest multiplicity (0 would violate)",
"default_until": 60
},
{
"name": "floor3",
"statement": "The q-continuant is injective on tails whose entries are all at least 3.",
"space": "tails with entries >= 3, ordered by entry sum up to N",
"miss_metric": "differing-coefficient count between two continuants of equal degree and equal value at 1",
"default_until": 24
},
{
"name": "negsum-period",
"statement": "Whether [sqrt(D)]_q + [-sqrt(D)]_q is a finite Laurent polynomial is decided by the continued fraction period of sqrt(D).",
"space": "non-square integers D up to N",
"miss_metric": "shared period length between two surds with opposite finiteness verdicts (shorter = nearer)",
"default_until": 60
},
{
"name": "down-closed",
"statement": "The cyclotomic index set of the denominator S of a reduced fraction a/d is downward closed for indices > 1: if the index-k cyclotomic factor divides S and l > 1 divides k, then the index-l factor divides S.",
"space": "reduced fractions a/d up to denominator N",
"miss_metric": "none reported (downward closure either holds or fails per fraction; the first failure is printed in full)",
"default_until": 60
},
{
"name": "residue-law",
"statement": "The index-5 cyclotomic factor divides the denominator S of a reduced fraction a/d if and only if 5 divides d and a == +/-1 (mod 5); this is Byakuno, Ren and Yanagawa 2026, Corollary 3.8 part 2.",
"space": "reduced fractions a/d up to denominator N",
"miss_metric": "none reported (the law is a sharp iff; the first mismatch in either direction is printed in full)",
"default_until": 60
}
]
}
Reverse table at one modulus: numerators grouped by identical S, residues per prime-power part, realized splits, and c(d).
worked example:
$ qreals collapse 12 --json
{
"d": 12,
"prime_powers": [
4,
3
],
"numerators_total": 4,
"groups": [
{
"numerators": [
1,
11
],
"klass": "FULL",
"T": [
2,
3,
4,
6,
12
],
"multiplicities": {
"2": 1,
"3": 1,
"4": 1,
"6": 1,
"12": 1
},
"S_factored": "Phi_2 * Phi_3 * Phi_4 * Phi_6 * Phi_12",
"residues": {
"4": [
1,
3
],
"3": [
1,
2
]
},
"ratio_numerators": [],
"splits": []
},
{
"numerators": [
5,
7
],
"klass": "COLLAPSE",
"T": [
2,
3,
4
],
"multiplicities": {
"2": 1,
"3": 1,
"4": 1
},
"S_factored": "Phi_2 * Phi_3 * Phi_4",
"residues": {
"4": [
1,
3
],
"3": [
2,
1
]
},
"ratio_numerators": [],
"splits": [
{
"d_plus": 1,
"d_minus": 12,
"discrepancy_class": "POLYNOMIAL",
"discrepancy": "Phi_6 Phi_12",
"realized_by": []
},
{
"d_plus": 3,
"d_minus": 4,
"discrepancy_class": "EXACT",
"discrepancy": "1",
"realized_by": [
5,
7
]
}
]
}
],
"c": 4,
"repeated_count": 0,
"noncyclotomic_count": 0,
"noncyclotomic_numerators": []
}
Replay a directory of claim files through the public CLI and report PASS or DRIFT per claim, under a total time budget.
worked example:
$ qreals check --show-schema
{
"schema": "the literal string 'qreals-claim/1'",
"tool": "a public qreals subcommand, e.g. 'denom'",
"args": "list of CLI argument strings (without --json)",
"expected_sha256": "hex SHA-256 of the tool's --json stdout",
"label": "free-text description; linted, ships publicly",
"runtime_seconds": "wall time of the recording run, float"
}
qreals.quadratic and qreals.negation add an exact-arithmetic engine for
studying G(x) = [x]_q + [-x]_q on quadratic irrationals x = a + b*sqrt(D),
with a, b rational and D a squarefree integer, alongside an exact closed-form
path for rational x.
-
qreals.quadratic.QuadraticIrrationalholds x = (p + r*sqrt(D)) / s exactly as integers p, r, s (s > 0, reduced), with exact add, subtract, scalar multiplication, reciprocal, negation, floor, and ceiling (no floating point in any comparison), plus a Hirzebruch-Jung (ceiling) continued-fraction iterator with period detection. -
qreals.negation.negation_sum_exact(x, depth)returns a verdict for G(x): for rational x it is exact ("finite" with the Laurent polynomial, or "infinite"), computed as a closed-form rational function of q; for x = a + b*sqrt(D) it locks Laurent coefficients by agreement between successive Hirzebruch-Jung convergents and reports "finite_looking", "infinite" (with the first confirmed nonzero tail coefficient), or "insufficient_depth". -
qreals.arithmetic.negation_sumis routed through this exact machinery for rational and quadratic inputs, falling back to the original truncated-series computation for other reals (transcendentals such as pi).
The negation-sweep subcommand builds an evidence grid at a fixed D over
growing denominators of a and b, and writes one CSV row per grid point plus a
running SUMMARY.md:
qreals negation-sweep --D 2 --qa-max 8 --qb-max 8 --pa-max 20 --pb-max 20 \
--depth 120 --min-zero-run 60 --out out-dir --workers 4 --resume
Each worker process owns a CSV shard file under out-dir (shard_0.csv,
shard_1.csv, ...) and flushes after every row; --resume reads every shard
already present and skips grid points already computed. SUMMARY.md is
rewritten periodically with counts by verdict, on-axis vs off-axis splits,
and any off-axis finite_looking hit flagged in capitals (an on-axis point
has b an integer and a = 0, i.e. x is an integer multiple of sqrt(D); an
off-axis finite hit would be evidence against the trace-zero-quadratic
criterion for Example 6.4 and is the reason the summary calls it out).
The web app works out of the box. These extras add the terminal interfaces:
pip install "qreals[app,proof,oeis]"| Extra | What it adds |
|---|---|
[app] |
Guided arrow-key menu, run qreals with no arguments |
[proof] |
Step-by-step certificates, run qreals certify |
[oeis] |
OEIS lookup, single (qreals oeis) and bulk (qreals oeis-sweep) |
[features] |
numpy for Fingerprint.as_numpy |
[fast] |
python-flint for fast exact polynomial arithmetic (large denominators) |
[mcp] |
the MCP server, run qreals mcp (see below) |
[ai] |
qreals explain, a Claude-written prose summary of a computed result |
[completion] |
tab completion for the qreals command |
qreals mcp runs a Model Context Protocol server over stdio, so Claude and other
MCP clients can compute q-deformations exactly instead of guessing them. The tools
cover exact q-rationals, coefficients, factorisation, denominator dossiers, jump
gaps, q-arithmetic, the negation panel (verdict labeled as a truncation-order
heuristic), and OEIS lookup.
pip install "qreals[mcp]"
claude mcp add qreals -- qreals mcpOr in a client configuration file:
{
"mcpServers": {
"qreals": { "command": "qreals", "args": ["mcp"] }
}
}The local web app doubles as an HTTP API: qreals serve exposes
POST /api/v1/compute with request validation and interactive OpenAPI docs at
/docs, alongside the JSON surface every subcommand already offers with --json.
MIT. See LICENSE.
Created by Patrick Taylor.


