Skip to content
patrickt6Public

About

Exact q-numbers, in Python and in the browser. A series in q that collapses back to x at q = 1.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

28 Commits

Folders and files

Repository files navigation

qreals: exact q-numbers, in Python and in the browser. A series in q that collapses back to x at q = 1.

How qreals works: pick a fraction p/s or a real x, fold the Morier-Genoud and Ovsienko continued fraction, get an exact rational function or series, and use it from Python, the CLI or the web app

PyPI License: MIT Python tests

Open the live app, no install needed, to compute q-numbers exactly in the browser.

The qreals web app computing the exact q-rational for 19/60

What is qreals

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.

At a glance

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.

Verification

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.

Developers

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).

1. Install

Windows (PowerShell):

py -m pip install qreals

macOS (Terminal):

python3 -m pip install qreals

2. Run the web app

qreals serve

This 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.

3. Update to the latest version

Re-run the install command with --upgrade to get the newest release:

Windows:

py -m pip install --upgrade qreals

macOS:

python3 -m pip install --upgrade qreals

Prefer 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.

What it does

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.

Features

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.

Worked example

$ 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.

Tool reference

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.

qreals denom

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"
      }
    ]
  }

qreals bricks

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
  }

qreals conj

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
      }
    ]
  }

qreals collapse

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": []
  }

qreals check

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"
  }

Negation-sum sweeps: G(x) = [x]_q + [-x]_q for a + b*sqrt(D)

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.QuadraticIrrational holds 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_sum is 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).

Optional extras

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

Use from AI agents (MCP)

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 mcp

Or 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.

License

MIT. See LICENSE.

Created by Patrick Taylor.

About

Exact q-numbers, in Python and in the browser. A series in q that collapses back to x at q = 1.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages